mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-30 04:48:36 +00:00
Compare commits
27 commits
1953d1e774
...
8c64979dcb
Author | SHA1 | Date | |
---|---|---|---|
8c64979dcb | |||
6e526d19f7 | |||
ec17fc4ca3 | |||
7b95b93c42 | |||
005e164751 | |||
bea627b646 | |||
81eafa9b78 | |||
5488d99b3e | |||
728049d6fa | |||
eb63ac74dc | |||
20f4c9af0f | |||
1e10e3a1c0 | |||
f82b1c1fcf | |||
fac940dfac | |||
96d682e5f7 | |||
96762f12e7 | |||
f98077591f | |||
0ca28d3a70 | |||
6e82d33eb7 | |||
0d5936563d | |||
b7a3023ca1 | |||
9f8d4d0b0a | |||
417b4cb453 | |||
9dfc402cc3 | |||
85fd5e283a | |||
867af68b17 | |||
802a52cb1b |
|
@ -158,7 +158,7 @@ M: Marcus Meissner <marcus@jet.franken.de>
|
|||
F: dlls/gphoto2.ds/
|
||||
|
||||
GStreamer multimedia backend
|
||||
M: Elizabeth Figura <zfigura@codeweavers.com>
|
||||
P: Elizabeth Figura <zfigura@codeweavers.com>
|
||||
P: Rémi Bernon <rbernon@codeweavers.com>
|
||||
F: dlls/winegstreamer/
|
||||
|
||||
|
|
|
@ -694,8 +694,9 @@ static void check_mft_set_input_type_required_(int line, IMFTransform *transform
|
|||
ok_(__FILE__, line)(!ref, "Release returned %lu\n", ref);
|
||||
}
|
||||
|
||||
#define check_mft_set_input_type(a, b) check_mft_set_input_type_(__LINE__, a, b, FALSE)
|
||||
static void check_mft_set_input_type_(int line, IMFTransform *transform, const struct attribute_desc *attributes, BOOL todo)
|
||||
#define check_mft_set_input_type(a, b, c) check_mft_set_input_type_(__LINE__, a, b, c, FALSE)
|
||||
static void check_mft_set_input_type_(int line, IMFTransform *transform, const struct attribute_desc *attributes,
|
||||
HRESULT expect_hr, BOOL todo)
|
||||
{
|
||||
IMFMediaType *media_type;
|
||||
HRESULT hr;
|
||||
|
@ -705,10 +706,10 @@ static void check_mft_set_input_type_(int line, IMFTransform *transform, const s
|
|||
init_media_type(media_type, attributes, -1);
|
||||
|
||||
hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
|
||||
ok_(__FILE__, line)(hr == S_OK, "SetInputType returned %#lx.\n", hr);
|
||||
ok_(__FILE__, line)(hr == expect_hr, "SetInputType returned %#lx.\n", hr);
|
||||
hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
|
||||
todo_wine_if(todo)
|
||||
ok_(__FILE__, line)(hr == S_OK, "SetInputType returned %#lx.\n", hr);
|
||||
ok_(__FILE__, line)(hr == expect_hr, "SetInputType returned %#lx.\n", hr);
|
||||
|
||||
IMFMediaType_Release(media_type);
|
||||
}
|
||||
|
@ -2154,7 +2155,7 @@ static void test_aac_encoder(void)
|
|||
check_mft_get_output_current_type(transform, expect_output_type_desc);
|
||||
|
||||
check_mft_set_input_type_required(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type(transform, expect_input_type_desc);
|
||||
|
||||
check_mft_get_input_stream_info(transform, S_OK, &input_info);
|
||||
|
@ -2412,7 +2413,7 @@ static void test_aac_decoder_subtype(const struct attribute_desc *input_type_des
|
|||
check_mft_get_output_current_type(transform, NULL);
|
||||
|
||||
check_mft_set_input_type_required(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type(transform, input_type_desc);
|
||||
|
||||
/* check new output media types */
|
||||
|
@ -2920,7 +2921,7 @@ static void test_wma_encoder(void)
|
|||
check_mft_get_output_current_type(transform, expect_output_type_desc);
|
||||
|
||||
check_mft_set_input_type_required(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type(transform, expect_input_type_desc);
|
||||
|
||||
check_mft_get_input_stream_info(transform, S_OK, &input_info);
|
||||
|
@ -3235,7 +3236,7 @@ static void test_wma_decoder(void)
|
|||
check_mft_get_output_current_type_(__LINE__, transform, NULL, TRUE, FALSE);
|
||||
|
||||
check_mft_set_input_type_required(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, TRUE, FALSE);
|
||||
|
||||
check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
|
||||
|
@ -3809,6 +3810,32 @@ static void test_h264_encoder(void)
|
|||
{.subtype = &MFVideoFormat_H264},
|
||||
},
|
||||
};
|
||||
static const media_type_desc default_outputs[] =
|
||||
{
|
||||
{
|
||||
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
|
||||
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
|
||||
},
|
||||
};
|
||||
static const media_type_desc default_inputs[] =
|
||||
{
|
||||
{
|
||||
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
|
||||
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
|
||||
},
|
||||
{
|
||||
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
|
||||
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
|
||||
},
|
||||
{
|
||||
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
|
||||
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
|
||||
},
|
||||
{
|
||||
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
|
||||
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
|
||||
},
|
||||
};
|
||||
static const struct attribute_desc expect_transform_attributes[] =
|
||||
{
|
||||
ATTR_UINT32(MFT_ENCODER_SUPPORTS_CONFIG_EVENT, 1),
|
||||
|
@ -3854,9 +3881,11 @@ static void test_h264_encoder(void)
|
|||
static const MFT_OUTPUT_STREAM_INFO expect_output_info = {.cbSize = 0x8000};
|
||||
MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_H264};
|
||||
MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_NV12};
|
||||
IMFMediaType *media_type;
|
||||
IMFTransform *transform;
|
||||
HRESULT hr;
|
||||
ULONG ret;
|
||||
DWORD i;
|
||||
|
||||
hr = CoInitialize(NULL);
|
||||
ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
|
||||
|
@ -3874,7 +3903,10 @@ static void test_h264_encoder(void)
|
|||
check_mft_get_info(class_id, &expect_mft_info);
|
||||
|
||||
hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform);
|
||||
todo_wine
|
||||
ok(hr == S_OK, "CoCreateInstance returned %#lx.\n", hr);
|
||||
if (hr != S_OK)
|
||||
goto failed;
|
||||
|
||||
check_interface(transform, &IID_IMFTransform, TRUE);
|
||||
check_interface(transform, &IID_IMediaObject, FALSE);
|
||||
|
@ -3885,17 +3917,49 @@ static void test_h264_encoder(void)
|
|||
check_mft_get_input_stream_info(transform, S_OK, NULL);
|
||||
check_mft_get_output_stream_info(transform, S_OK, NULL);
|
||||
|
||||
/* No input type is available before an output type is set. */
|
||||
hr = IMFTransform_GetInputAvailableType(transform, 0, 0, &media_type);
|
||||
ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputAvailableType returned %#lx\n", hr);
|
||||
check_mft_set_input_type(transform, input_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
|
||||
check_mft_get_input_current_type(transform, NULL);
|
||||
|
||||
/* Check available output types. */
|
||||
i = -1;
|
||||
while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
|
||||
{
|
||||
winetest_push_context("out %lu", i);
|
||||
ok(hr == S_OK, "GetOutputAvailableType returned %#lx.\n", hr);
|
||||
check_media_type(media_type, default_outputs[i], -1);
|
||||
ret = IMFMediaType_Release(media_type);
|
||||
ok(ret == 0, "Release returned %lu\n", ret);
|
||||
winetest_pop_context();
|
||||
}
|
||||
ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx.\n", hr);
|
||||
ok(i == ARRAY_SIZE(default_outputs), "%lu output media types.\n", i);
|
||||
|
||||
check_mft_set_output_type_required(transform, output_type_desc);
|
||||
check_mft_set_output_type(transform, output_type_desc, S_OK);
|
||||
check_mft_get_output_current_type(transform, expect_output_type_desc);
|
||||
check_mft_get_output_stream_info(transform, S_OK, &expect_output_info);
|
||||
|
||||
/* Input types can now be enumerated. */
|
||||
i = -1;
|
||||
while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
|
||||
{
|
||||
winetest_push_context("out %lu", i);
|
||||
ok(hr == S_OK, "IMFTransform_GetInputAvailableType returned %#lx\n", hr);
|
||||
check_media_type(media_type, default_inputs[i], -1);
|
||||
ret = IMFMediaType_Release(media_type);
|
||||
ok(ret == 0, "Release returned %lu\n", ret);
|
||||
winetest_pop_context();
|
||||
}
|
||||
ok(hr == MF_E_NO_MORE_TYPES, "IMFTransform_GetInputAvailableType returned %#lx\n", hr);
|
||||
ok(i == ARRAY_SIZE(default_inputs), "%lu input media types\n", i);
|
||||
|
||||
check_mft_set_input_type_required(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type(transform, expect_input_type_desc);
|
||||
|
||||
check_mft_get_output_current_type(transform, expect_output_type_desc);
|
||||
|
||||
check_mft_get_input_stream_info(transform, S_OK, NULL);
|
||||
check_mft_get_output_stream_info(transform, S_OK, &expect_output_info);
|
||||
|
||||
ret = IMFTransform_Release(transform);
|
||||
ok(ret == 0, "Release returned %lu\n", ret);
|
||||
|
@ -4294,7 +4358,7 @@ static void test_h264_decoder(void)
|
|||
ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
|
||||
|
||||
check_mft_set_input_type_required(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
|
||||
|
||||
check_mft_get_input_stream_info(transform, S_OK, &input_info);
|
||||
|
@ -4971,7 +5035,7 @@ static void test_audio_convert(void)
|
|||
check_mft_get_output_current_type(transform, NULL);
|
||||
|
||||
check_mft_set_input_type_required(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
|
||||
|
||||
check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
|
||||
|
@ -5446,7 +5510,7 @@ static void test_wmv_encoder(void)
|
|||
check_mft_get_output_current_type(transform, NULL);
|
||||
|
||||
check_mft_set_input_type_required(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
|
||||
|
||||
check_mft_set_output_type_required(transform, output_type_desc);
|
||||
|
@ -6034,7 +6098,7 @@ static void test_wmv_decoder(void)
|
|||
check_mft_get_output_current_type(transform, NULL);
|
||||
|
||||
check_mft_set_input_type_required(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
|
||||
|
||||
i = -1;
|
||||
|
@ -7159,7 +7223,7 @@ static void test_color_convert(void)
|
|||
ok(i == 20, "%lu input media types\n", i);
|
||||
|
||||
check_mft_set_input_type_required(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(color_conversion_tests); i++)
|
||||
|
@ -7939,7 +8003,7 @@ static void test_video_processor(void)
|
|||
ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
|
||||
|
||||
/* MFVideoFormat_ABGR32 isn't supported by the video processor in non-D3D mode */
|
||||
check_mft_set_input_type(transform, nv12_default_stride);
|
||||
check_mft_set_input_type(transform, nv12_default_stride, S_OK);
|
||||
|
||||
hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
|
||||
ok(hr == S_OK, "got %#lx\n", hr);
|
||||
|
@ -7961,7 +8025,7 @@ static void test_video_processor(void)
|
|||
winetest_push_context("transform #%lu", i);
|
||||
|
||||
check_mft_set_input_type_required(transform, test->input_type_desc);
|
||||
check_mft_set_input_type(transform, test->input_type_desc);
|
||||
check_mft_set_input_type(transform, test->input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type(transform, test->input_type_desc);
|
||||
|
||||
if (i >= 15)
|
||||
|
@ -8111,13 +8175,13 @@ skip_test:
|
|||
&IID_IMFTransform, (void **)&transform);
|
||||
ok(hr == S_OK, "got hr %#lx\n", hr);
|
||||
|
||||
check_mft_set_input_type(transform, nv12_no_aperture);
|
||||
check_mft_set_input_type(transform, nv12_no_aperture, S_OK);
|
||||
check_mft_get_input_current_type(transform, nv12_no_aperture);
|
||||
|
||||
check_mft_set_output_type(transform, rgb32_no_aperture, S_OK);
|
||||
check_mft_get_output_current_type(transform, rgb32_no_aperture);
|
||||
|
||||
check_mft_set_input_type_(__LINE__, transform, nv12_with_aperture, TRUE);
|
||||
check_mft_set_input_type_(__LINE__, transform, nv12_with_aperture, S_OK, TRUE);
|
||||
check_mft_get_input_current_type_(__LINE__, transform, nv12_with_aperture, TRUE, FALSE);
|
||||
|
||||
/* output type is the same as before */
|
||||
|
@ -8376,7 +8440,7 @@ static void test_mp3_decoder(void)
|
|||
check_mft_get_output_current_type(transform, NULL);
|
||||
|
||||
check_mft_set_input_type_required(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc);
|
||||
check_mft_set_input_type(transform, input_type_desc, S_OK);
|
||||
check_mft_get_input_current_type(transform, expect_input_type_desc);
|
||||
|
||||
check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
|
||||
|
@ -9427,7 +9491,7 @@ static void test_video_processor_with_dxgi_manager(void)
|
|||
|
||||
/* check RGB32 output aperture cropping with D3D buffers */
|
||||
|
||||
check_mft_set_input_type(transform, nv12_with_aperture);
|
||||
check_mft_set_input_type(transform, nv12_with_aperture, S_OK);
|
||||
check_mft_set_output_type_(__LINE__, transform, rgb32_no_aperture, S_OK, TRUE);
|
||||
|
||||
load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
|
||||
|
@ -9495,7 +9559,7 @@ static void test_video_processor_with_dxgi_manager(void)
|
|||
skip_rgb32:
|
||||
/* check ABGR32 output with D3D buffers */
|
||||
|
||||
check_mft_set_input_type(transform, nv12_with_aperture);
|
||||
check_mft_set_input_type(transform, nv12_with_aperture, S_OK);
|
||||
check_mft_set_output_type_(__LINE__, transform, abgr32_no_aperture, S_OK, TRUE);
|
||||
|
||||
load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
|
||||
|
|
|
@ -787,7 +787,7 @@ static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags,
|
|||
return hres;
|
||||
}
|
||||
|
||||
hres = IDispatchEx_QueryInterface(&This->IDispatchEx_iface, tid_ids[func->tid], (void**)&unk);
|
||||
hres = IWineJSDispatchHost_QueryInterface(&This->IWineJSDispatchHost_iface, tid_ids[func->tid], (void**)&unk);
|
||||
if(FAILED(hres)) {
|
||||
ERR("Could not get iface %s: %08lx\n", debugstr_mshtml_guid(tid_ids[func->tid]), hres);
|
||||
return E_FAIL;
|
||||
|
@ -799,6 +799,138 @@ static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags,
|
|||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT get_disp_prop(IDispatchEx *dispex, const WCHAR *name, LCID lcid, VARIANT *res,
|
||||
EXCEPINFO *ei, IServiceProvider *caller)
|
||||
{
|
||||
DISPPARAMS dp = { 0 };
|
||||
DISPID dispid;
|
||||
HRESULT hres;
|
||||
BSTR bstr;
|
||||
|
||||
if(!(bstr = SysAllocString(name)))
|
||||
return E_OUTOFMEMORY;
|
||||
hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid);
|
||||
SysFreeString(bstr);
|
||||
if(SUCCEEDED(hres))
|
||||
hres = IDispatchEx_InvokeEx(dispex, dispid, lcid, DISPATCH_PROPERTYGET, &dp, res, ei, caller);
|
||||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT function_apply(func_disp_t *func, DISPPARAMS *dp, LCID lcid, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
|
||||
{
|
||||
IWineJSDispatchHost *this_iface;
|
||||
DISPPARAMS params = { 0 };
|
||||
IDispatchEx *array = NULL;
|
||||
UINT argc = 0;
|
||||
VARIANT *arg;
|
||||
HRESULT hres;
|
||||
|
||||
arg = dp->rgvarg + dp->cArgs - 1;
|
||||
if(dp->cArgs < 1 || V_VT(arg) != VT_DISPATCH || !V_DISPATCH(arg))
|
||||
return CTL_E_ILLEGALFUNCTIONCALL;
|
||||
|
||||
hres = IDispatch_QueryInterface(V_DISPATCH(arg), &IID_IWineJSDispatchHost, (void**)&this_iface);
|
||||
if(FAILED(hres))
|
||||
return CTL_E_ILLEGALFUNCTIONCALL;
|
||||
|
||||
if(dp->cArgs >= 2) {
|
||||
VARIANT length;
|
||||
|
||||
arg--;
|
||||
if(V_VT(arg) != VT_DISPATCH) {
|
||||
hres = CTL_E_ILLEGALFUNCTIONCALL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* FIXME: Native checks if it's an acual JS array. */
|
||||
hres = IDispatch_QueryInterface(V_DISPATCH(arg), &IID_IDispatchEx, (void**)&array);
|
||||
if(FAILED(hres))
|
||||
goto fail;
|
||||
|
||||
V_VT(&length) = VT_EMPTY;
|
||||
hres = get_disp_prop(array, L"length", lcid, &length, ei, caller);
|
||||
if(FAILED(hres)) {
|
||||
if(hres == DISP_E_UNKNOWNNAME)
|
||||
hres = CTL_E_ILLEGALFUNCTIONCALL;
|
||||
goto fail;
|
||||
}
|
||||
if(V_VT(&length) != VT_I4) {
|
||||
VARIANT tmp = length;
|
||||
hres = change_type(&length, &tmp, VT_I4, caller);
|
||||
if(FAILED(hres)) {
|
||||
hres = CTL_E_ILLEGALFUNCTIONCALL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if(V_I4(&length) < 0) {
|
||||
hres = CTL_E_ILLEGALFUNCTIONCALL;
|
||||
goto fail;
|
||||
}
|
||||
params.cArgs = V_I4(&length);
|
||||
|
||||
/* alloc new params */
|
||||
if(params.cArgs) {
|
||||
if(!(params.rgvarg = malloc(params.cArgs * sizeof(VARIANTARG)))) {
|
||||
hres = E_OUTOFMEMORY;
|
||||
goto fail;
|
||||
}
|
||||
for(argc = 0; argc < params.cArgs; argc++) {
|
||||
WCHAR buf[12];
|
||||
|
||||
arg = params.rgvarg + params.cArgs - argc - 1;
|
||||
swprintf(buf, ARRAY_SIZE(buf), L"%u", argc);
|
||||
hres = get_disp_prop(array, buf, lcid, arg, ei, caller);
|
||||
if(FAILED(hres)) {
|
||||
if(hres == DISP_E_UNKNOWNNAME) {
|
||||
V_VT(arg) = VT_EMPTY;
|
||||
continue;
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, func->info->tid, ¶ms, res, ei, caller);
|
||||
|
||||
fail:
|
||||
while(argc--)
|
||||
VariantClear(¶ms.rgvarg[params.cArgs - argc - 1]);
|
||||
free(params.rgvarg);
|
||||
if(array)
|
||||
IDispatchEx_Release(array);
|
||||
IWineJSDispatchHost_Release(this_iface);
|
||||
return hres == E_UNEXPECTED ? CTL_E_ILLEGALFUNCTIONCALL : hres;
|
||||
}
|
||||
|
||||
static HRESULT function_call(func_disp_t *func, DISPPARAMS *dp, LCID lcid, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
|
||||
{
|
||||
DISPPARAMS params = { dp->rgvarg, NULL, dp->cArgs - 1, 0 };
|
||||
IWineJSDispatchHost *this_iface;
|
||||
VARIANT *arg;
|
||||
HRESULT hres;
|
||||
|
||||
arg = dp->rgvarg + dp->cArgs - 1;
|
||||
if(dp->cArgs < 1 || V_VT(arg) != VT_DISPATCH || !V_DISPATCH(arg))
|
||||
return CTL_E_ILLEGALFUNCTIONCALL;
|
||||
|
||||
hres = IDispatch_QueryInterface(V_DISPATCH(arg), &IID_IWineJSDispatchHost, (void**)&this_iface);
|
||||
if(FAILED(hres))
|
||||
return CTL_E_ILLEGALFUNCTIONCALL;
|
||||
|
||||
hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, func->info->tid, ¶ms, res, ei, caller);
|
||||
IWineJSDispatchHost_Release(this_iface);
|
||||
return (hres == E_UNEXPECTED) ? CTL_E_ILLEGALFUNCTIONCALL : hres;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const WCHAR *name;
|
||||
HRESULT (*invoke)(func_disp_t*,DISPPARAMS*,LCID,VARIANT*,EXCEPINFO*,IServiceProvider*);
|
||||
} function_props[] = {
|
||||
{ L"apply", function_apply },
|
||||
{ L"call", function_call }
|
||||
};
|
||||
|
||||
static inline func_disp_t *impl_from_DispatchEx(DispatchEx *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, func_disp_t, dispex);
|
||||
|
@ -866,9 +998,58 @@ static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
|
|||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT function_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(function_props); i++) {
|
||||
if((flags & fdexNameCaseInsensitive) ? wcsicmp(name, function_props[i].name) : wcscmp(name, function_props[i].name))
|
||||
continue;
|
||||
*dispid = MSHTML_DISPID_CUSTOM_MIN + i;
|
||||
return S_OK;
|
||||
}
|
||||
return DISP_E_UNKNOWNNAME;
|
||||
}
|
||||
|
||||
static HRESULT function_get_name(DispatchEx *dispex, DISPID id, BSTR *name)
|
||||
{
|
||||
DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN;
|
||||
|
||||
if(idx >= ARRAY_SIZE(function_props))
|
||||
return DISP_E_MEMBERNOTFOUND;
|
||||
|
||||
return (*name = SysAllocString(function_props[idx].name)) ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
static HRESULT function_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
|
||||
VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
|
||||
{
|
||||
func_disp_t *This = impl_from_DispatchEx(dispex);
|
||||
DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN;
|
||||
|
||||
if(idx >= ARRAY_SIZE(function_props))
|
||||
return DISP_E_MEMBERNOTFOUND;
|
||||
|
||||
switch(flags) {
|
||||
case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
|
||||
if(!res)
|
||||
return E_INVALIDARG;
|
||||
/* fall through */
|
||||
case DISPATCH_METHOD:
|
||||
return function_props[idx].invoke(This, params, lcid, res, ei, caller);
|
||||
default:
|
||||
return MSHTML_E_INVALID_PROPERTY;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const dispex_static_data_vtbl_t function_dispex_vtbl = {
|
||||
.destructor = function_destructor,
|
||||
.value = function_value,
|
||||
.get_dispid = function_get_dispid,
|
||||
.get_name = function_get_name,
|
||||
.invoke = function_invoke
|
||||
};
|
||||
|
||||
static const tid_t function_iface_tids[] = {0};
|
||||
|
@ -916,7 +1097,7 @@ static HRESULT invoke_disp_value(DispatchEx *This, IDispatch *func_disp, LCID lc
|
|||
memcpy(new_dp.rgvarg+1, dp->rgvarg, dp->cArgs*sizeof(VARIANTARG));
|
||||
|
||||
V_VT(new_dp.rgvarg) = VT_DISPATCH;
|
||||
V_DISPATCH(new_dp.rgvarg) = (IDispatch*)&This->IDispatchEx_iface;
|
||||
V_DISPATCH(new_dp.rgvarg) = (IDispatch*)&This->IWineJSDispatchHost_iface;
|
||||
|
||||
hres = IDispatch_QueryInterface(func_disp, &IID_IDispatchEx, (void**)&dispex);
|
||||
TRACE(">>>\n");
|
||||
|
@ -957,9 +1138,9 @@ static HRESULT get_func_obj_entry(DispatchEx *This, func_info_t *func, func_obj_
|
|||
if(!entry->func_obj)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
IDispatchEx_AddRef(&entry->func_obj->dispex.IDispatchEx_iface);
|
||||
IWineJSDispatchHost_AddRef(&entry->func_obj->dispex.IWineJSDispatchHost_iface);
|
||||
V_VT(&entry->val) = VT_DISPATCH;
|
||||
V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface;
|
||||
V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface;
|
||||
}
|
||||
|
||||
*ret = entry;
|
||||
|
@ -1082,7 +1263,7 @@ static HRESULT builtin_propget(DispatchEx *This, func_info_t *func, DISPPARAMS *
|
|||
|
||||
assert(func->get_vtbl_off);
|
||||
|
||||
hres = IDispatchEx_QueryInterface(&This->IDispatchEx_iface, tid_ids[func->tid], (void**)&iface);
|
||||
hres = IWineJSDispatchHost_QueryInterface(&This->IWineJSDispatchHost_iface, tid_ids[func->tid], (void**)&iface);
|
||||
if(SUCCEEDED(hres)) {
|
||||
switch(func->prop_vt) {
|
||||
#define CASE_VT(vt,type,access) \
|
||||
|
@ -1139,7 +1320,7 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS *
|
|||
v = &tmpv;
|
||||
}
|
||||
|
||||
hres = IDispatchEx_QueryInterface(&This->IDispatchEx_iface, tid_ids[func->tid], (void**)&iface);
|
||||
hres = IWineJSDispatchHost_QueryInterface(&This->IWineJSDispatchHost_iface, tid_ids[func->tid], (void**)&iface);
|
||||
if(SUCCEEDED(hres)) {
|
||||
switch(func->prop_vt) {
|
||||
#define CASE_VT(vt,type,access) \
|
||||
|
@ -1161,8 +1342,8 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS *
|
|||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp,
|
||||
VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
|
||||
static HRESULT call_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp,
|
||||
VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
|
||||
{
|
||||
VARIANT arg_buf[MAX_ARGS], *arg_ptrs[MAX_ARGS], *arg, retv, ret_ref, vhres;
|
||||
unsigned i, nconv = 0;
|
||||
|
@ -1183,7 +1364,7 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP
|
|||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
hres = IDispatchEx_QueryInterface(&This->IDispatchEx_iface, tid_ids[func->tid], (void**)&iface);
|
||||
hres = IWineJSDispatchHost_QueryInterface(&This->IWineJSDispatchHost_iface, tid_ids[func->tid], (void**)&iface);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
|
@ -1268,7 +1449,7 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP
|
|||
return V_ERROR(&vhres);
|
||||
}
|
||||
|
||||
static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
|
||||
static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
|
||||
EXCEPINFO *ei, IServiceProvider *caller)
|
||||
{
|
||||
HRESULT hres;
|
||||
|
@ -1288,7 +1469,7 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags,
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
if((IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface != V_DISPATCH(&entry->val)) {
|
||||
if((IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface != V_DISPATCH(&entry->val)) {
|
||||
if(!V_DISPATCH(&entry->val)) {
|
||||
FIXME("Calling null\n");
|
||||
return E_FAIL;
|
||||
|
@ -1299,7 +1480,7 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags,
|
|||
}
|
||||
}
|
||||
|
||||
hres = invoke_builtin_function(This, func, dp, res, ei, caller);
|
||||
hres = call_builtin_function(This, func, dp, res, ei, caller);
|
||||
break;
|
||||
case DISPATCH_PROPERTYGET: {
|
||||
func_obj_entry_t *entry;
|
||||
|
@ -1365,7 +1546,7 @@ static HRESULT invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD
|
|||
return hres;
|
||||
|
||||
if(func->func_disp_idx >= 0)
|
||||
return function_invoke(This, func, flags, dp, res, ei, caller);
|
||||
return invoke_builtin_function(This, func, flags, dp, res, ei, caller);
|
||||
|
||||
if(func->hook) {
|
||||
hres = func->hook(This, flags, dp, res, ei, caller);
|
||||
|
@ -1422,7 +1603,7 @@ HRESULT dispex_call_builtin(DispatchEx *dispex, DISPID id, DISPPARAMS *dp,
|
|||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
return invoke_builtin_function(dispex, func, dp, res, ei, caller);
|
||||
return call_builtin_function(dispex, func, dp, res, ei, caller);
|
||||
}
|
||||
|
||||
HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success)
|
||||
|
@ -1464,14 +1645,14 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success)
|
|||
|
||||
entry = This->dynamic_data->func_disps + func->func_disp_idx;
|
||||
if(V_VT(&entry->val) == VT_DISPATCH
|
||||
&& V_DISPATCH(&entry->val) == (IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface) {
|
||||
&& V_DISPATCH(&entry->val) == (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface) {
|
||||
*success = VARIANT_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
VariantClear(&entry->val);
|
||||
V_VT(&entry->val) = VT_DISPATCH;
|
||||
V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface;
|
||||
V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface;
|
||||
IDispatch_AddRef(V_DISPATCH(&entry->val));
|
||||
*success = VARIANT_TRUE;
|
||||
return S_OK;
|
||||
|
@ -1549,14 +1730,14 @@ static BOOL ensure_real_info(DispatchEx *dispex)
|
|||
return dispex->info != NULL;
|
||||
}
|
||||
|
||||
static inline DispatchEx *impl_from_IDispatchEx(IDispatchEx *iface)
|
||||
static inline DispatchEx *impl_from_IWineJSDispatchHost(IWineJSDispatchHost *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, DispatchEx, IDispatchEx_iface);
|
||||
return CONTAINING_RECORD(iface, DispatchEx, IWineJSDispatchHost_iface);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
|
||||
static HRESULT WINAPI DispatchEx_QueryInterface(IWineJSDispatchHost *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
TRACE("%s (%p)->(%s %p)\n", This->info->desc->name, This, debugstr_mshtml_guid(riid), ppv);
|
||||
|
||||
|
@ -1567,12 +1748,14 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid,
|
|||
}
|
||||
|
||||
if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_IDispatchEx, riid))
|
||||
*ppv = &This->IDispatchEx_iface;
|
||||
*ppv = &This->IWineJSDispatchHost_iface;
|
||||
else if(IsEqualGUID(&IID_IWineJSDispatchHost, riid))
|
||||
*ppv = &This->IWineJSDispatchHost_iface;
|
||||
else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
|
||||
*ppv = &dispex_ccp;
|
||||
return S_OK;
|
||||
}else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
|
||||
*ppv = &This->IDispatchEx_iface;
|
||||
*ppv = &This->IWineJSDispatchHost_iface;
|
||||
return S_OK;
|
||||
}else if(IsEqualGUID(&IID_IDispatchJS, riid) ||
|
||||
IsEqualGUID(&IID_UndocumentedScriptIface, riid) ||
|
||||
|
@ -1587,24 +1770,24 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid,
|
|||
}
|
||||
|
||||
ret:
|
||||
IDispatchEx_AddRef(&This->IDispatchEx_iface);
|
||||
IWineJSDispatchHost_AddRef(&This->IWineJSDispatchHost_iface);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface)
|
||||
static ULONG WINAPI DispatchEx_AddRef(IWineJSDispatchHost *iface)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
LONG ref = ccref_incr(&This->ccref, (nsISupports*)&This->IDispatchEx_iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
LONG ref = ccref_incr(&This->ccref, (nsISupports*)&This->IWineJSDispatchHost_iface);
|
||||
|
||||
TRACE("%s (%p) ref=%ld\n", This->info->desc->name, This, ref);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
|
||||
static ULONG WINAPI DispatchEx_Release(IWineJSDispatchHost *iface)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IDispatchEx_iface, &dispex_ccp);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IWineJSDispatchHost_iface, &dispex_ccp);
|
||||
|
||||
TRACE("%s (%p) ref=%ld\n", This->info->desc->name, This, ref);
|
||||
|
||||
|
@ -1612,17 +1795,17 @@ static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
|
|||
* an extra care for objects that need an immediate clean up. See Gecko's
|
||||
* NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE_WITH_LAST_RELEASE for details. */
|
||||
if(!ref && This->info->desc->vtbl->last_release) {
|
||||
ccref_incr(&This->ccref, (nsISupports*)&This->IDispatchEx_iface);
|
||||
ccref_incr(&This->ccref, (nsISupports*)&This->IWineJSDispatchHost_iface);
|
||||
This->info->desc->vtbl->last_release(This);
|
||||
ccref_decr(&This->ccref, (nsISupports*)&This->IDispatchEx_iface, &dispex_ccp);
|
||||
ccref_decr(&This->ccref, (nsISupports*)&This->IWineJSDispatchHost_iface, &dispex_ccp);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
|
||||
static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IWineJSDispatchHost *iface, UINT *pctinfo)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
TRACE("%s (%p)->(%p)\n", This->info->desc->name, This, pctinfo);
|
||||
|
||||
|
@ -1630,10 +1813,10 @@ static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pcti
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
|
||||
LCID lcid, ITypeInfo **ppTInfo)
|
||||
static HRESULT WINAPI DispatchEx_GetTypeInfo(IWineJSDispatchHost *iface, UINT iTInfo,
|
||||
LCID lcid, ITypeInfo **ppTInfo)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("%s (%p)->(%u %lu %p)\n", This->info->desc->name, This, iTInfo, lcid, ppTInfo);
|
||||
|
@ -1646,11 +1829,11 @@ static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
|
||||
LPOLESTR *rgszNames, UINT cNames,
|
||||
LCID lcid, DISPID *rgDispId)
|
||||
static HRESULT WINAPI DispatchEx_GetIDsOfNames(IWineJSDispatchHost *iface, REFIID riid,
|
||||
LPOLESTR *rgszNames, UINT cNames,
|
||||
LCID lcid, DISPID *rgDispId)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
HRESULT hres = S_OK;
|
||||
|
||||
TRACE("%s (%p)->(%s %p %u %lu %p)\n", This->info->desc->name, This, debugstr_guid(riid), rgszNames,
|
||||
|
@ -1658,27 +1841,27 @@ static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
|
|||
|
||||
/* Native ignores all cNames > 1, and doesn't even fill them */
|
||||
if(cNames)
|
||||
hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[0], 0, rgDispId);
|
||||
hres = IWineJSDispatchHost_GetDispID(&This->IWineJSDispatchHost_iface, rgszNames[0], 0, rgDispId);
|
||||
|
||||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
|
||||
static HRESULT WINAPI DispatchEx_Invoke(IWineJSDispatchHost *iface, DISPID dispIdMember,
|
||||
REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
|
||||
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
TRACE("%s (%p)->(%ld %s %ld %d %p %p %p %p)\n", This->info->desc->name, This, dispIdMember,
|
||||
debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
|
||||
|
||||
return IDispatchEx_InvokeEx(&This->IDispatchEx_iface, dispIdMember, lcid, wFlags, pDispParams,
|
||||
return IWineJSDispatchHost_InvokeEx(&This->IWineJSDispatchHost_iface, dispIdMember, lcid, wFlags, pDispParams,
|
||||
pVarResult, pExcepInfo, NULL);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
|
||||
static HRESULT WINAPI DispatchEx_GetDispID(IWineJSDispatchHost *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
dynamic_prop_t *dprop = NULL;
|
||||
HRESULT hres;
|
||||
|
||||
|
@ -1711,10 +1894,10 @@ static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
|
||||
static HRESULT WINAPI DispatchEx_InvokeEx(IWineJSDispatchHost *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
|
||||
VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("%s (%p)->(%lx %lx %x %p %p %p %p)\n", This->info->desc->name, This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
|
||||
|
@ -1803,9 +1986,9 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
|
|||
}
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR name, DWORD grfdex)
|
||||
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IWineJSDispatchHost *iface, BSTR name, DWORD grfdex)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
DISPID id;
|
||||
HRESULT hres;
|
||||
|
||||
|
@ -1814,7 +1997,7 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR nam
|
|||
if(dispex_compat_mode(This) < COMPAT_MODE_IE8 && !This->info->desc->vtbl->delete)
|
||||
return E_NOTIMPL;
|
||||
|
||||
hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, name, grfdex & ~fdexNameEnsure, &id);
|
||||
hres = IWineJSDispatchHost_GetDispID(&This->IWineJSDispatchHost_iface, name, grfdex & ~fdexNameEnsure, &id);
|
||||
if(FAILED(hres)) {
|
||||
compat_mode_t compat_mode = dispex_compat_mode(This);
|
||||
TRACE("property %s not found\n", debugstr_w(name));
|
||||
|
@ -1822,12 +2005,12 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR nam
|
|||
compat_mode < COMPAT_MODE_IE9 ? hres : S_OK;
|
||||
}
|
||||
|
||||
return IDispatchEx_DeleteMemberByDispID(&This->IDispatchEx_iface, id);
|
||||
return IWineJSDispatchHost_DeleteMemberByDispID(&This->IWineJSDispatchHost_iface, id);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
|
||||
static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IWineJSDispatchHost *iface, DISPID id)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
TRACE("%s (%p)->(%lx)\n", This->info->desc->name, This, id);
|
||||
|
||||
|
@ -1855,16 +2038,16 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
|
||||
static HRESULT WINAPI DispatchEx_GetMemberProperties(IWineJSDispatchHost *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
FIXME("%s (%p)->(%lx %lx %p)\n", This->info->desc->name, This, id, grfdexFetch, pgrfdex);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
|
||||
static HRESULT WINAPI DispatchEx_GetMemberName(IWineJSDispatchHost *iface, DISPID id, BSTR *pbstrName)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
func_info_t *func;
|
||||
HRESULT hres;
|
||||
|
||||
|
@ -1917,9 +2100,9 @@ static HRESULT next_dynamic_id(DispatchEx *dispex, DWORD idx, DISPID *ret_id)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
|
||||
static HRESULT WINAPI DispatchEx_GetNextDispID(IWineJSDispatchHost *iface, DWORD grfdex, DISPID id, DISPID *pid)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
func_info_t *func;
|
||||
HRESULT hres;
|
||||
|
||||
|
@ -1971,14 +2154,31 @@ static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex,
|
|||
return S_FALSE;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
|
||||
static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IWineJSDispatchHost *iface, IUnknown **ppunk)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(iface);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
FIXME("%s (%p)->(%p)\n", This->info->desc->name, This, ppunk);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static IDispatchExVtbl DispatchExVtbl = {
|
||||
static HRESULT WINAPI DispatchEx_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret,
|
||||
EXCEPINFO *ei, IServiceProvider *caller)
|
||||
{
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
|
||||
func_info_t *func;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("%s (%p)->(%lx %x %p %p %p %p)\n", This->info->desc->name, This, id, iid, dp, ret, ei, caller);
|
||||
|
||||
hres = get_builtin_func(This->info, id, &func);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
if(func->tid != iid || func->func_disp_idx < 0)
|
||||
return E_UNEXPECTED;
|
||||
return call_builtin_function(This, func, dp, ret, ei, caller);
|
||||
}
|
||||
|
||||
static IWineJSDispatchHostVtbl JSDispatchHostVtbl = {
|
||||
DispatchEx_QueryInterface,
|
||||
DispatchEx_AddRef,
|
||||
DispatchEx_Release,
|
||||
|
@ -1993,12 +2193,13 @@ static IDispatchExVtbl DispatchExVtbl = {
|
|||
DispatchEx_GetMemberProperties,
|
||||
DispatchEx_GetMemberName,
|
||||
DispatchEx_GetNextDispID,
|
||||
DispatchEx_GetNameSpaceParent
|
||||
DispatchEx_GetNameSpaceParent,
|
||||
DispatchEx_CallFunction,
|
||||
};
|
||||
|
||||
static nsresult NSAPI dispex_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(p);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(p);
|
||||
dynamic_prop_t *prop;
|
||||
|
||||
describe_cc_node(&This->ccref, This->info->desc->name, cb);
|
||||
|
@ -2018,7 +2219,7 @@ static nsresult NSAPI dispex_traverse(void *ccp, void *p, nsCycleCollectionTrave
|
|||
for(iter = This->dynamic_data->func_disps; iter < end; iter++) {
|
||||
if(!iter->func_obj)
|
||||
continue;
|
||||
note_cc_edge((nsISupports*)&iter->func_obj->dispex.IDispatchEx_iface, "func_obj", cb);
|
||||
note_cc_edge((nsISupports*)&iter->func_obj->dispex.IWineJSDispatchHost_iface, "func_obj", cb);
|
||||
traverse_variant(&iter->val, "func_val", cb);
|
||||
}
|
||||
}
|
||||
|
@ -2045,7 +2246,7 @@ void dispex_props_unlink(DispatchEx *This)
|
|||
if(!iter->func_obj)
|
||||
continue;
|
||||
iter->func_obj->obj = NULL;
|
||||
IDispatchEx_Release(&iter->func_obj->dispex.IDispatchEx_iface);
|
||||
IWineJSDispatchHost_Release(&iter->func_obj->dispex.IWineJSDispatchHost_iface);
|
||||
VariantClear(&iter->val);
|
||||
}
|
||||
|
||||
|
@ -2056,7 +2257,7 @@ void dispex_props_unlink(DispatchEx *This)
|
|||
|
||||
static nsresult NSAPI dispex_unlink(void *p)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(p);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(p);
|
||||
|
||||
if(This->info->desc->vtbl->unlink)
|
||||
This->info->desc->vtbl->unlink(This);
|
||||
|
@ -2067,7 +2268,7 @@ static nsresult NSAPI dispex_unlink(void *p)
|
|||
|
||||
static void NSAPI dispex_delete_cycle_collectable(void *p)
|
||||
{
|
||||
DispatchEx *This = impl_from_IDispatchEx(p);
|
||||
DispatchEx *This = impl_from_IWineJSDispatchHost(p);
|
||||
dynamic_prop_t *prop;
|
||||
|
||||
if(This->info->desc->vtbl->unlink)
|
||||
|
@ -2089,7 +2290,7 @@ static void NSAPI dispex_delete_cycle_collectable(void *p)
|
|||
for(iter = This->dynamic_data->func_disps; iter < This->dynamic_data->func_disps + This->info->func_disp_cnt; iter++) {
|
||||
if(iter->func_obj) {
|
||||
iter->func_obj->obj = NULL;
|
||||
IDispatchEx_Release(&iter->func_obj->dispex.IDispatchEx_iface);
|
||||
IWineJSDispatchHost_Release(&iter->func_obj->dispex.IWineJSDispatchHost_iface);
|
||||
}
|
||||
VariantClear(&iter->val);
|
||||
}
|
||||
|
@ -2122,7 +2323,7 @@ void init_dispatch(DispatchEx *dispex, dispex_static_data_t *data, compat_mode_t
|
|||
{
|
||||
assert(compat_mode < COMPAT_MODE_CNT);
|
||||
|
||||
dispex->IDispatchEx_iface.lpVtbl = &DispatchExVtbl;
|
||||
dispex->IWineJSDispatchHost_iface.lpVtbl = &JSDispatchHostVtbl;
|
||||
dispex->dynamic_data = NULL;
|
||||
ccref_init(&dispex->ccref, 1);
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ static HRESULT WINAPI HTMLDOMAttribute_get_nodeName(IHTMLDOMAttribute *iface, BS
|
|||
return *p ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
return IDispatchEx_GetMemberName(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, p);
|
||||
return IWineJSDispatchHost_GetMemberName(&This->elem->node.event_target.dispex.IWineJSDispatchHost_iface, This->dispid, p);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI HTMLDOMAttribute_put_nodeValue(IHTMLDOMAttribute *iface, VARIANT v)
|
||||
|
@ -73,7 +73,7 @@ static HRESULT WINAPI HTMLDOMAttribute_put_nodeValue(IHTMLDOMAttribute *iface, V
|
|||
|
||||
memset(&ei, 0, sizeof(ei));
|
||||
|
||||
return IDispatchEx_InvokeEx(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, LOCALE_SYSTEM_DEFAULT,
|
||||
return IWineJSDispatchHost_InvokeEx(&This->elem->node.event_target.dispex.IWineJSDispatchHost_iface, This->dispid, LOCALE_SYSTEM_DEFAULT,
|
||||
DISPATCH_PROPERTYPUT, &dp, &ret, &ei, NULL);
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ static HRESULT WINAPI HTMLDOMAttribute_get_specified(IHTMLDOMAttribute *iface, V
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
hres = IDispatchEx_GetMemberName(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, &name);
|
||||
hres = IWineJSDispatchHost_GetMemberName(&This->elem->node.event_target.dispex.IWineJSDispatchHost_iface, This->dispid, &name);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
|
|
|
@ -5529,8 +5529,8 @@ static HRESULT HTMLDocumentNode_location_hook(DispatchEx *dispex, WORD flags, DI
|
|||
if(!This->window->base.outer_window)
|
||||
return E_FAIL;
|
||||
|
||||
return IDispatchEx_InvokeEx(&This->window->event_target.dispex.IDispatchEx_iface, DISPID_IHTMLWINDOW2_LOCATION,
|
||||
0, flags, dp, res, ei, caller);
|
||||
return IWineJSDispatchHost_InvokeEx(&This->window->event_target.dispex.IWineJSDispatchHost_iface,
|
||||
DISPID_IHTMLWINDOW2_LOCATION, 0, flags, dp, res, ei, caller);
|
||||
}
|
||||
|
||||
static HRESULT HTMLDocumentNode_pre_handle_event(DispatchEx* dispex, DOMEvent *event)
|
||||
|
|
|
@ -1170,7 +1170,7 @@ static HRESULT set_elem_attr_value_by_dispid(HTMLElement *elem, DISPID dispid, V
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
return IDispatchEx_InvokeEx(&elem->node.event_target.dispex.IDispatchEx_iface, dispid,
|
||||
return IWineJSDispatchHost_InvokeEx(&elem->node.event_target.dispex.IWineJSDispatchHost_iface, dispid,
|
||||
LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, NULL);
|
||||
}
|
||||
|
||||
|
@ -1189,7 +1189,7 @@ static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttr
|
|||
TRACE("(%p)->(%s %s %08lx)\n", This, debugstr_w(strAttributeName), debugstr_variant(&AttributeValue), lFlags);
|
||||
|
||||
if(compat_mode < COMPAT_MODE_IE9 || !This->dom_element) {
|
||||
hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface, translate_attr_name(strAttributeName, compat_mode),
|
||||
hres = IWineJSDispatchHost_GetDispID(&This->node.event_target.dispex.IWineJSDispatchHost_iface, translate_attr_name(strAttributeName, compat_mode),
|
||||
(lFlags&ATTRFLAG_CASESENSITIVE ? fdexNameCaseSensitive : fdexNameCaseInsensitive) | fdexNameEnsure, &dispid);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
@ -1241,7 +1241,7 @@ HRESULT get_elem_attr_value_by_dispid(HTMLElement *elem, DISPID dispid, VARIANT
|
|||
DISPPARAMS dispParams = {NULL, NULL, 0, 0};
|
||||
EXCEPINFO excep;
|
||||
|
||||
return IDispatchEx_InvokeEx(&elem->node.event_target.dispex.IDispatchEx_iface, dispid, LOCALE_SYSTEM_DEFAULT,
|
||||
return IWineJSDispatchHost_InvokeEx(&elem->node.event_target.dispex.IWineJSDispatchHost_iface, dispid, LOCALE_SYSTEM_DEFAULT,
|
||||
DISPATCH_PROPERTYGET, &dispParams, ret, &excep, NULL);
|
||||
}
|
||||
|
||||
|
@ -1288,7 +1288,7 @@ static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttr
|
|||
FIXME("Unsupported flags %lx\n", lFlags);
|
||||
|
||||
if(compat_mode < COMPAT_MODE_IE9 || !This->dom_element) {
|
||||
hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface, translate_attr_name(strAttributeName, compat_mode),
|
||||
hres = IWineJSDispatchHost_GetDispID(&This->node.event_target.dispex.IWineJSDispatchHost_iface, translate_attr_name(strAttributeName, compat_mode),
|
||||
lFlags&ATTRFLAG_CASESENSITIVE ? fdexNameCaseSensitive : fdexNameCaseInsensitive, &dispid);
|
||||
if(FAILED(hres)) {
|
||||
V_VT(AttributeValue) = VT_NULL;
|
||||
|
@ -1336,7 +1336,7 @@ static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strA
|
|||
TRACE("(%p)->(%s %lx %p)\n", This, debugstr_w(strAttributeName), lFlags, pfSuccess);
|
||||
|
||||
if(compat_mode < COMPAT_MODE_IE9 || !This->dom_element) {
|
||||
hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface, translate_attr_name(strAttributeName, compat_mode),
|
||||
hres = IWineJSDispatchHost_GetDispID(&This->node.event_target.dispex.IWineJSDispatchHost_iface, translate_attr_name(strAttributeName, compat_mode),
|
||||
lFlags&ATTRFLAG_CASESENSITIVE ? fdexNameCaseSensitive : fdexNameCaseInsensitive, &id);
|
||||
if(hres == DISP_E_UNKNOWNNAME) {
|
||||
*pfSuccess = VARIANT_FALSE;
|
||||
|
@ -2483,7 +2483,7 @@ static HRESULT WINAPI HTMLElement_toString(IHTMLElement *iface, BSTR *String)
|
|||
if(!String)
|
||||
return E_INVALIDARG;
|
||||
|
||||
hres = IDispatchEx_InvokeEx(&This->node.event_target.dispex.IDispatchEx_iface, DISPID_VALUE,
|
||||
hres = IWineJSDispatchHost_InvokeEx(&This->node.event_target.dispex.IWineJSDispatchHost_iface, DISPID_VALUE,
|
||||
LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, NULL, &var, NULL, NULL);
|
||||
if(SUCCEEDED(hres)) {
|
||||
assert(V_VT(&var) == VT_BSTR);
|
||||
|
@ -4429,7 +4429,7 @@ static HRESULT WINAPI HTMLElement4_setAttributeNode(IHTMLElement4 *iface, IHTMLD
|
|||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface,
|
||||
hres = IWineJSDispatchHost_GetDispID(&This->node.event_target.dispex.IWineJSDispatchHost_iface,
|
||||
attr->name, fdexNameCaseInsensitive|fdexNameEnsure, &dispid);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
@ -6399,7 +6399,7 @@ HRESULT HTMLElement_populate_props(DispatchEx *dispex)
|
|||
continue;
|
||||
}
|
||||
|
||||
hres = IDispatchEx_GetDispID(&dispex->IDispatchEx_iface, name, fdexNameCaseInsensitive, &id);
|
||||
hres = IWineJSDispatchHost_GetDispID(&dispex->IWineJSDispatchHost_iface, name, fdexNameCaseInsensitive, &id);
|
||||
if(hres != DISP_E_UNKNOWNNAME) {
|
||||
nsIDOMAttr_Release(attr);
|
||||
SysFreeString(name);
|
||||
|
@ -7544,7 +7544,7 @@ static HRESULT create_filters_collection(compat_mode_t compat_mode, IHTMLFilters
|
|||
|
||||
static HRESULT get_attr_dispid_by_relative_idx(HTMLAttributeCollection *This, LONG *idx, DISPID start, DISPID *dispid)
|
||||
{
|
||||
IDispatchEx *dispex = &This->elem->node.event_target.dispex.IDispatchEx_iface;
|
||||
IWineJSDispatchHost *dispex = &This->elem->node.event_target.dispex.IWineJSDispatchHost_iface;
|
||||
DISPID id = start;
|
||||
LONG len = -1;
|
||||
HRESULT hres;
|
||||
|
@ -7552,7 +7552,7 @@ static HRESULT get_attr_dispid_by_relative_idx(HTMLAttributeCollection *This, LO
|
|||
FIXME("filter non-enumerable attributes out\n");
|
||||
|
||||
while(1) {
|
||||
hres = IDispatchEx_GetNextDispID(dispex, fdexEnumAll, id, &id);
|
||||
hres = IWineJSDispatchHost_GetNextDispID(dispex, fdexEnumAll, id, &id);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
else if(hres == S_FALSE)
|
||||
|
@ -7593,7 +7593,7 @@ static inline HRESULT get_attr_dispid_by_name(HTMLAttributeCollection *This, BST
|
|||
}
|
||||
}
|
||||
|
||||
hres = IDispatchEx_GetDispID(&This->elem->node.event_target.dispex.IDispatchEx_iface,
|
||||
hres = IWineJSDispatchHost_GetDispID(&This->elem->node.event_target.dispex.IWineJSDispatchHost_iface,
|
||||
name, fdexNameCaseInsensitive, id);
|
||||
return hres;
|
||||
}
|
||||
|
|
|
@ -315,7 +315,7 @@ static BOOL is_elem_name(HTMLElement *elem, LPCWSTR name)
|
|||
static HRESULT get_item_idx(HTMLElementCollection *This, UINT idx, IDispatch **ret)
|
||||
{
|
||||
if(idx < This->len) {
|
||||
*ret = (IDispatch*)&This->elems[idx]->node.event_target.dispex.IDispatchEx_iface;
|
||||
*ret = (IDispatch*)&This->elems[idx]->node.event_target.dispex.IWineJSDispatchHost_iface;
|
||||
IDispatch_AddRef(*ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -2056,7 +2056,7 @@ static HRESULT WINAPI DOMEvent_get_srcElement(IDOMEvent *iface, IHTMLElement **p
|
|||
TRACE("(%p)->(%p)\n", This, p);
|
||||
|
||||
if(This->target)
|
||||
IDispatchEx_QueryInterface(&This->target->dispex.IDispatchEx_iface, &IID_IHTMLElement, (void**)p);
|
||||
IWineJSDispatchHost_QueryInterface(&This->target->dispex.IWineJSDispatchHost_iface, &IID_IHTMLElement, (void**)p);
|
||||
else
|
||||
*p = NULL;
|
||||
return S_OK;
|
||||
|
@ -4167,7 +4167,7 @@ static void call_event_handlers(EventTarget *event_target, DOMEvent *event, disp
|
|||
skip_onevent_listener = TRUE;
|
||||
|
||||
V_VT(&arg) = VT_DISPATCH;
|
||||
V_DISPATCH(&arg) = (IDispatch*)&event_target->dispex.IDispatchEx_iface;
|
||||
V_DISPATCH(&arg) = (IDispatch*)&event_target->dispex.IWineJSDispatchHost_iface;
|
||||
V_VT(&v) = VT_EMPTY;
|
||||
if(vtbl->get_dispatch_this)
|
||||
V_DISPATCH(&arg) = vtbl->get_dispatch_this(&event_target->dispex);
|
||||
|
@ -4249,7 +4249,7 @@ static void call_event_handlers(EventTarget *event_target, DOMEvent *event, disp
|
|||
DISPPARAMS dp = {args, &named_arg, 2, 1};
|
||||
|
||||
V_VT(args) = VT_DISPATCH;
|
||||
V_DISPATCH(args) = (IDispatch*)&event_target->dispex.IDispatchEx_iface;
|
||||
V_DISPATCH(args) = (IDispatch*)&event_target->dispex.IWineJSDispatchHost_iface;
|
||||
if(vtbl->get_dispatch_this)
|
||||
V_DISPATCH(args) = vtbl->get_dispatch_this(&event_target->dispex);
|
||||
IDispatch_AddRef(V_DISPATCH(args));
|
||||
|
|
|
@ -893,7 +893,7 @@ static HRESULT HTMLFrameElement_invoke(DispatchEx *dispex, DISPID id, LCID lcid,
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
return IDispatchEx_InvokeEx(&This->framebase.content_window->IDispatchEx_iface, id, lcid,
|
||||
return IWineJSDispatchHost_InvokeEx(&This->framebase.content_window->IWineJSDispatchHost_iface, id, lcid,
|
||||
flags, params, res, ei, caller);
|
||||
}
|
||||
|
||||
|
@ -1330,7 +1330,7 @@ static HRESULT HTMLIFrame_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
return IDispatchEx_InvokeEx(&This->framebase.content_window->IDispatchEx_iface, id, lcid,
|
||||
return IWineJSDispatchHost_InvokeEx(&This->framebase.content_window->IWineJSDispatchHost_iface, id, lcid,
|
||||
flags, params, res, ei, caller);
|
||||
}
|
||||
|
||||
|
|
|
@ -2917,7 +2917,7 @@ static HRESULT WINAPI HTMLStyle_removeAttribute(IHTMLStyle *iface, BSTR strAttri
|
|||
DISPID dispid;
|
||||
unsigned i;
|
||||
|
||||
hres = IDispatchEx_GetDispID(&This->css_style.dispex.IDispatchEx_iface, strAttributeName,
|
||||
hres = IWineJSDispatchHost_GetDispID(&This->css_style.dispex.IWineJSDispatchHost_iface, strAttributeName,
|
||||
(lFlags&1) ? fdexNameCaseSensitive : fdexNameCaseInsensitive, &dispid);
|
||||
if(hres != S_OK) {
|
||||
*pfSuccess = VARIANT_FALSE;
|
||||
|
|
|
@ -211,8 +211,8 @@ static HRESULT WINAPI outer_window_QueryInterface(IHTMLWindow2 *iface, REFIID ri
|
|||
}else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
|
||||
*ppv = &This->base.IHTMLWindow2_iface;
|
||||
return S_OK;
|
||||
}else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
|
||||
*ppv = &This->IDispatchEx_iface;
|
||||
}else if(IsEqualGUID(&IID_IDispatchEx, riid) || IsEqualGUID(&IID_IWineJSDispatchHost, riid)) {
|
||||
*ppv = &This->IWineJSDispatchHost_iface;
|
||||
}else if(IsEqualGUID(&IID_IEventTarget, riid)) {
|
||||
if(!This->base.inner_window->doc || This->base.inner_window->doc->document_mode < COMPAT_MODE_IE9)
|
||||
return E_NOINTERFACE;
|
||||
|
@ -3277,34 +3277,34 @@ static const IWineHTMLWindowCompatPrivateVtbl WineHTMLWindowCompatPrivateVtbl =
|
|||
window_compat_private_get_performance,
|
||||
};
|
||||
|
||||
static inline HTMLOuterWindow *impl_from_IDispatchEx(IDispatchEx *iface)
|
||||
static inline HTMLOuterWindow *impl_from_IWineJSDispatchHost(IWineJSDispatchHost *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, HTMLOuterWindow, IDispatchEx_iface);
|
||||
return CONTAINING_RECORD(iface, HTMLOuterWindow, IWineJSDispatchHost_iface);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI WindowDispEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
|
||||
static HRESULT WINAPI WindowDispEx_QueryInterface(IWineJSDispatchHost *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
return IHTMLWindow2_QueryInterface(&This->base.IHTMLWindow2_iface, riid, ppv);
|
||||
}
|
||||
|
||||
static ULONG WINAPI WindowDispEx_AddRef(IDispatchEx *iface)
|
||||
static ULONG WINAPI WindowDispEx_AddRef(IWineJSDispatchHost *iface)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
return IHTMLWindow2_AddRef(&This->base.IHTMLWindow2_iface);
|
||||
}
|
||||
|
||||
static ULONG WINAPI WindowDispEx_Release(IDispatchEx *iface)
|
||||
static ULONG WINAPI WindowDispEx_Release(IWineJSDispatchHost *iface)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
return IHTMLWindow2_Release(&This->base.IHTMLWindow2_iface);
|
||||
}
|
||||
|
||||
DISPEX_IDISPATCH_NOUNK_IMPL(WindowDispEx, IDispatchEx,
|
||||
impl_from_IDispatchEx(iface)->base.inner_window->event_target.dispex)
|
||||
DISPEX_IDISPATCH_NOUNK_IMPL(WindowDispEx, IWineJSDispatchHost,
|
||||
impl_from_IWineJSDispatchHost(iface)->base.inner_window->event_target.dispex)
|
||||
|
||||
static global_prop_t *alloc_global_prop(HTMLInnerWindow *This, global_prop_type_t type, BSTR name)
|
||||
{
|
||||
|
@ -3369,69 +3369,70 @@ HRESULT search_window_props(HTMLInnerWindow *This, BSTR bstrName, DWORD grfdex,
|
|||
return DISP_E_UNKNOWNNAME;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI WindowDispEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
|
||||
static HRESULT WINAPI WindowDispEx_GetDispID(IWineJSDispatchHost *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
return IDispatchEx_GetDispID(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, bstrName, grfdex, pid);
|
||||
return IWineJSDispatchHost_GetDispID(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, bstrName, grfdex, pid);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI WindowDispEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
|
||||
static HRESULT WINAPI WindowDispEx_InvokeEx(IWineJSDispatchHost *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
|
||||
VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
|
||||
return IDispatchEx_InvokeEx(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
return IWineJSDispatchHost_InvokeEx(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id, lcid, wFlags,
|
||||
pdp, pvarRes, pei, pspCaller);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI WindowDispEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
|
||||
static HRESULT WINAPI WindowDispEx_DeleteMemberByName(IWineJSDispatchHost *iface, BSTR bstrName, DWORD grfdex)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
TRACE("(%p)->(%s %lx)\n", This, debugstr_w(bstrName), grfdex);
|
||||
|
||||
return IDispatchEx_DeleteMemberByName(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, bstrName, grfdex);
|
||||
return IWineJSDispatchHost_DeleteMemberByName(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, bstrName, grfdex);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI WindowDispEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
|
||||
static HRESULT WINAPI WindowDispEx_DeleteMemberByDispID(IWineJSDispatchHost *iface, DISPID id)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
TRACE("(%p)->(%lx)\n", This, id);
|
||||
|
||||
return IDispatchEx_DeleteMemberByDispID(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, id);
|
||||
return IWineJSDispatchHost_DeleteMemberByDispID(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI WindowDispEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
|
||||
static HRESULT WINAPI WindowDispEx_GetMemberProperties(IWineJSDispatchHost *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
TRACE("(%p)->(%lx %lx %p)\n", This, id, grfdexFetch, pgrfdex);
|
||||
|
||||
return IDispatchEx_GetMemberProperties(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, id, grfdexFetch,
|
||||
return IWineJSDispatchHost_GetMemberProperties(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id, grfdexFetch,
|
||||
pgrfdex);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI WindowDispEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
|
||||
static HRESULT WINAPI WindowDispEx_GetMemberName(IWineJSDispatchHost *iface, DISPID id, BSTR *pbstrName)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
TRACE("(%p)->(%lx %p)\n", This, id, pbstrName);
|
||||
|
||||
return IDispatchEx_GetMemberName(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, id, pbstrName);
|
||||
return IWineJSDispatchHost_GetMemberName(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id, pbstrName);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI WindowDispEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
|
||||
static HRESULT WINAPI WindowDispEx_GetNextDispID(IWineJSDispatchHost *iface, DWORD grfdex, DISPID id, DISPID *pid)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
TRACE("(%p)->(%lx %lx %p)\n", This, grfdex, id, pid);
|
||||
|
||||
return IDispatchEx_GetNextDispID(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, grfdex, id, pid);
|
||||
return IWineJSDispatchHost_GetNextDispID(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, grfdex, id, pid);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI WindowDispEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
|
||||
static HRESULT WINAPI WindowDispEx_GetNameSpaceParent(IWineJSDispatchHost *iface, IUnknown **ppunk)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
TRACE("(%p)->(%p)\n", This, ppunk);
|
||||
|
||||
|
@ -3439,7 +3440,16 @@ static HRESULT WINAPI WindowDispEx_GetNameSpaceParent(IDispatchEx *iface, IUnkno
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static const IDispatchExVtbl WindowDispExVtbl = {
|
||||
static HRESULT WINAPI WindowDispEx_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret,
|
||||
EXCEPINFO *ei, IServiceProvider *caller)
|
||||
{
|
||||
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
|
||||
|
||||
return IWineJSDispatchHost_CallFunction(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface,
|
||||
id, iid, dp, ret, ei, caller);
|
||||
}
|
||||
|
||||
static const IWineJSDispatchHostVtbl WindowDispExVtbl = {
|
||||
WindowDispEx_QueryInterface,
|
||||
WindowDispEx_AddRef,
|
||||
WindowDispEx_Release,
|
||||
|
@ -3454,7 +3464,8 @@ static const IDispatchExVtbl WindowDispExVtbl = {
|
|||
WindowDispEx_GetMemberProperties,
|
||||
WindowDispEx_GetMemberName,
|
||||
WindowDispEx_GetNextDispID,
|
||||
WindowDispEx_GetNameSpaceParent
|
||||
WindowDispEx_GetNameSpaceParent,
|
||||
WindowDispEx_CallFunction,
|
||||
};
|
||||
|
||||
static inline HTMLOuterWindow *impl_from_IEventTarget(IEventTarget *iface)
|
||||
|
@ -3810,7 +3821,7 @@ static HRESULT HTMLWindow_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD
|
|||
|
||||
prop->type = GLOBAL_DISPEXVAR;
|
||||
prop->id = dispex_id;
|
||||
return IDispatchEx_InvokeEx(&This->event_target.dispex.IDispatchEx_iface, dispex_id, 0, flags, params, res, ei, caller);
|
||||
return IWineJSDispatchHost_InvokeEx(&This->event_target.dispex.IWineJSDispatchHost_iface, dispex_id, 0, flags, params, res, ei, caller);
|
||||
}
|
||||
default:
|
||||
FIXME("Not supported flags: %x\n", flags);
|
||||
|
@ -3838,7 +3849,7 @@ static HRESULT HTMLWindow_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
case GLOBAL_DISPEXVAR:
|
||||
return IDispatchEx_InvokeEx(&This->event_target.dispex.IDispatchEx_iface, prop->id, 0, flags, params, res, ei, caller);
|
||||
return IWineJSDispatchHost_InvokeEx(&This->event_target.dispex.IWineJSDispatchHost_iface, prop->id, 0, flags, params, res, ei, caller);
|
||||
default:
|
||||
ERR("invalid type %d\n", prop->type);
|
||||
hres = DISP_E_MEMBERNOTFOUND;
|
||||
|
@ -3901,7 +3912,7 @@ static HRESULT IHTMLWindow2_location_hook(DispatchEx *dispex, WORD flags, DISPPA
|
|||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = IDispatchEx_InvokeEx(&location->dispex.IDispatchEx_iface, DISPID_VALUE, 0, flags, dp, res, ei, caller);
|
||||
hres = IWineJSDispatchHost_InvokeEx(&location->dispex.IWineJSDispatchHost_iface, DISPID_VALUE, 0, flags, dp, res, ei, caller);
|
||||
IHTMLLocation_Release(&location->IHTMLLocation_iface);
|
||||
return hres;
|
||||
}
|
||||
|
@ -4204,7 +4215,7 @@ HRESULT create_outer_window(GeckoBrowser *browser, mozIDOMWindowProxy *mozwindow
|
|||
if(!window)
|
||||
return E_OUTOFMEMORY;
|
||||
window->base.IHTMLWindow2_iface.lpVtbl = &outer_window_HTMLWindow2Vtbl;
|
||||
window->IDispatchEx_iface.lpVtbl = &WindowDispExVtbl;
|
||||
window->IWineJSDispatchHost_iface.lpVtbl = &WindowDispExVtbl;
|
||||
window->IEventTarget_iface.lpVtbl = &EventTargetVtbl;
|
||||
|
||||
window->base.outer_window = window;
|
||||
|
|
|
@ -413,7 +413,7 @@ typedef struct {
|
|||
} dispex_hook_t;
|
||||
|
||||
struct DispatchEx {
|
||||
IDispatchEx IDispatchEx_iface;
|
||||
IWineJSDispatchHost IWineJSDispatchHost_iface;
|
||||
|
||||
nsCycleCollectingAutoRefCnt ccref;
|
||||
|
||||
|
@ -424,38 +424,38 @@ struct DispatchEx {
|
|||
#define DISPEX_IDISPATCH_NOUNK_IMPL(prefix, iface_name, dispex) \
|
||||
static HRESULT WINAPI prefix##_GetTypeInfoCount(iface_name *iface, UINT *count) \
|
||||
{ \
|
||||
return IDispatchEx_GetTypeInfoCount(&(dispex).IDispatchEx_iface, count); \
|
||||
return IWineJSDispatchHost_GetTypeInfoCount(&(dispex).IWineJSDispatchHost_iface, count); \
|
||||
} \
|
||||
static HRESULT WINAPI prefix##_GetTypeInfo(iface_name *iface, \
|
||||
UINT index, LCID lcid, ITypeInfo **ret) \
|
||||
{ \
|
||||
return IDispatchEx_GetTypeInfo(&(dispex).IDispatchEx_iface, index, lcid, ret); \
|
||||
return IWineJSDispatchHost_GetTypeInfo(&(dispex).IWineJSDispatchHost_iface, index, lcid, ret); \
|
||||
} \
|
||||
static HRESULT WINAPI prefix##_GetIDsOfNames(iface_name *iface, REFIID riid, \
|
||||
LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) \
|
||||
{ \
|
||||
return IDispatchEx_GetIDsOfNames(&(dispex).IDispatchEx_iface, \
|
||||
return IWineJSDispatchHost_GetIDsOfNames(&(dispex).IWineJSDispatchHost_iface, \
|
||||
riid, names, count, lcid, dispid); \
|
||||
} \
|
||||
static HRESULT WINAPI prefix##_Invoke(iface_name *iface, DISPID dispid, REFIID riid, \
|
||||
LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, UINT *err) \
|
||||
{ \
|
||||
return IDispatchEx_Invoke(&(dispex).IDispatchEx_iface, dispid, \
|
||||
return IWineJSDispatchHost_Invoke(&(dispex).IWineJSDispatchHost_iface, dispid, \
|
||||
riid, lcid, flags, params, res, ei, err); \
|
||||
}
|
||||
|
||||
#define DISPEX_IDISPATCH_IMPL(prefix, iface_name, dispex) \
|
||||
static HRESULT WINAPI prefix##_QueryInterface(iface_name *iface, REFIID riid, void **ppv) \
|
||||
{ \
|
||||
return IDispatchEx_QueryInterface(&(dispex).IDispatchEx_iface, riid, ppv); \
|
||||
return IWineJSDispatchHost_QueryInterface(&(dispex).IWineJSDispatchHost_iface, riid, ppv); \
|
||||
} \
|
||||
static ULONG WINAPI prefix##_AddRef(iface_name *iface) \
|
||||
{ \
|
||||
return IDispatchEx_AddRef(&(dispex).IDispatchEx_iface); \
|
||||
return IWineJSDispatchHost_AddRef(&(dispex).IWineJSDispatchHost_iface); \
|
||||
} \
|
||||
static ULONG WINAPI prefix##_Release(iface_name *iface) \
|
||||
{ \
|
||||
return IDispatchEx_Release(&(dispex).IDispatchEx_iface); \
|
||||
return IWineJSDispatchHost_Release(&(dispex).IWineJSDispatchHost_iface); \
|
||||
} \
|
||||
DISPEX_IDISPATCH_NOUNK_IMPL(prefix, iface_name, dispex)
|
||||
|
||||
|
@ -594,7 +594,7 @@ struct HTMLWindow {
|
|||
struct HTMLOuterWindow {
|
||||
HTMLWindow base;
|
||||
IEventTarget IEventTarget_iface;
|
||||
IDispatchEx IDispatchEx_iface;
|
||||
IWineJSDispatchHost IWineJSDispatchHost_iface;
|
||||
|
||||
nsCycleCollectingAutoRefCnt ccref;
|
||||
LONG task_magic;
|
||||
|
|
|
@ -258,3 +258,13 @@ interface IWineXMLHttpRequestPrivate : IDispatch
|
|||
}
|
||||
|
||||
} /* library MSHTML_private */
|
||||
|
||||
[
|
||||
object,
|
||||
uuid(d359f2fe-5531-741b-a41a-5cf92edc971b),
|
||||
local
|
||||
]
|
||||
interface IWineJSDispatchHost : IDispatchEx
|
||||
{
|
||||
HRESULT CallFunction(DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller);
|
||||
}
|
||||
|
|
|
@ -1301,6 +1301,6 @@ HRESULT create_mutation_observer_ctor(compat_mode_t compat_mode, IDispatch **ret
|
|||
|
||||
init_dispatch(&obj->dispex, &mutation_observer_ctor_dispex, compat_mode);
|
||||
|
||||
*ret = (IDispatch *)&obj->dispex.IDispatchEx_iface;
|
||||
*ret = (IDispatch *)&obj->dispex.IWineJSDispatchHost_iface;
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -3542,7 +3542,7 @@ static HRESULT WINAPI DocObjDispatchEx_GetDispID(IDispatchEx *iface, BSTR name,
|
|||
{
|
||||
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
|
||||
|
||||
return IDispatchEx_GetDispID(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, name, grfdex, pid);
|
||||
return IWineJSDispatchHost_GetDispID(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, name, grfdex, pid);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DocObjDispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
|
||||
|
@ -3550,29 +3550,29 @@ static HRESULT WINAPI DocObjDispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, L
|
|||
{
|
||||
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
|
||||
|
||||
return IDispatchEx_InvokeEx(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, id, lcid,
|
||||
wFlags, pdp, pvarRes, pei, pspCaller);
|
||||
return IWineJSDispatchHost_InvokeEx(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, id, lcid,
|
||||
wFlags, pdp, pvarRes, pei, pspCaller);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DocObjDispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
|
||||
{
|
||||
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
|
||||
|
||||
return IDispatchEx_DeleteMemberByName(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, bstrName, grfdex);
|
||||
return IWineJSDispatchHost_DeleteMemberByName(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, bstrName, grfdex);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DocObjDispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
|
||||
{
|
||||
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
|
||||
|
||||
return IDispatchEx_DeleteMemberByDispID(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, id);
|
||||
return IWineJSDispatchHost_DeleteMemberByDispID(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, id);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DocObjDispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
|
||||
{
|
||||
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
|
||||
|
||||
return IDispatchEx_GetMemberProperties(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, id, grfdexFetch,
|
||||
return IWineJSDispatchHost_GetMemberProperties(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, id, grfdexFetch,
|
||||
pgrfdex);
|
||||
}
|
||||
|
||||
|
@ -3580,21 +3580,21 @@ static HRESULT WINAPI DocObjDispatchEx_GetMemberName(IDispatchEx *iface, DISPID
|
|||
{
|
||||
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
|
||||
|
||||
return IDispatchEx_GetMemberName(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, id, name);
|
||||
return IWineJSDispatchHost_GetMemberName(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, id, name);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DocObjDispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
|
||||
{
|
||||
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
|
||||
|
||||
return IDispatchEx_GetNextDispID(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, grfdex, id, pid);
|
||||
return IWineJSDispatchHost_GetNextDispID(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, grfdex, id, pid);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DocObjDispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
|
||||
{
|
||||
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
|
||||
|
||||
return IDispatchEx_GetNameSpaceParent(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, ppunk);
|
||||
return IWineJSDispatchHost_GetNameSpaceParent(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, ppunk);
|
||||
}
|
||||
|
||||
static const IDispatchExVtbl DocObjDispatchExVtbl = {
|
||||
|
|
|
@ -2313,7 +2313,7 @@ static nsresult NSAPI media_query_list_callback_HandleChange(nsIDOMMediaQueryLis
|
|||
DISPPARAMS dp = { args, NULL, 1, 0 };
|
||||
|
||||
V_VT(args) = VT_DISPATCH;
|
||||
V_DISPATCH(args) = (IDispatch*)&media_query_list->dispex.IDispatchEx_iface;
|
||||
V_DISPATCH(args) = (IDispatch*)&media_query_list->dispex.IWineJSDispatchHost_iface;
|
||||
V_VT(&v) = VT_EMPTY;
|
||||
|
||||
TRACE("%p >>>\n", media_query_list);
|
||||
|
|
|
@ -1573,7 +1573,7 @@ static EventTarget *find_event_target(HTMLDocumentNode *doc, HTMLScriptElement *
|
|||
}else if(!wcscmp(target_id, L"window")) {
|
||||
if(doc->window) {
|
||||
event_target = &doc->window->event_target;
|
||||
IDispatchEx_AddRef(&event_target->dispex.IDispatchEx_iface);
|
||||
IWineJSDispatchHost_AddRef(&event_target->dispex.IWineJSDispatchHost_iface);
|
||||
}
|
||||
}else {
|
||||
HTMLElement *target_elem;
|
||||
|
@ -1731,14 +1731,14 @@ void bind_event_scripts(HTMLDocumentNode *doc)
|
|||
if(event_disp) {
|
||||
event_target = find_event_target(doc, script_elem);
|
||||
if(event_target) {
|
||||
hres = IDispatchEx_QueryInterface(&event_target->dispex.IDispatchEx_iface, &IID_HTMLPluginContainer,
|
||||
hres = IWineJSDispatchHost_QueryInterface(&event_target->dispex.IWineJSDispatchHost_iface, &IID_HTMLPluginContainer,
|
||||
(void**)&plugin_container);
|
||||
if(SUCCEEDED(hres))
|
||||
bind_activex_event(doc, plugin_container, event, event_disp);
|
||||
else
|
||||
bind_target_event(doc, event_target, event, event_disp);
|
||||
|
||||
IDispatchEx_Release(&event_target->dispex.IDispatchEx_iface);
|
||||
IWineJSDispatchHost_Release(&event_target->dispex.IWineJSDispatchHost_iface);
|
||||
if(plugin_container)
|
||||
node_release(&plugin_container->element.node);
|
||||
}
|
||||
|
|
|
@ -352,6 +352,73 @@ sync_test("builtin_toString", function() {
|
|||
}
|
||||
});
|
||||
|
||||
sync_test("builtin_obj", function() {
|
||||
var v = document.documentMode;
|
||||
var f = document.createElement;
|
||||
var e;
|
||||
|
||||
if(v < 9) {
|
||||
ok(!(window instanceof Object), "window instance of Object");
|
||||
ok(!(document instanceof Object), "document instance of Object");
|
||||
ok(!("arguments" in f), "arguments in f");
|
||||
ok(!("length" in f), "length in f");
|
||||
e = 0;
|
||||
try {
|
||||
f.toString();
|
||||
}catch(ex) {
|
||||
e = ex.number;
|
||||
}
|
||||
ok(e === 0xa01b6 - 0x80000000, "[f.toString] e = " + e);
|
||||
try {
|
||||
window.toString.call(null);
|
||||
ok(false, "expected exception calling window.toString with null context");
|
||||
}catch(ex) {}
|
||||
}
|
||||
|
||||
e = 0;
|
||||
try {
|
||||
f.call(Object, "div");
|
||||
}catch(ex) {
|
||||
e = ex.number;
|
||||
}
|
||||
todo_wine_if(v >= 9).
|
||||
ok(e === (v < 9 ? 0xa0005 : 0x0ffff) - 0x80000000, "[f.call(Object, 'div')] e = " + e);
|
||||
|
||||
e = 0;
|
||||
try {
|
||||
f.call(null, "div");
|
||||
}catch(ex) {
|
||||
e = ex.number;
|
||||
}
|
||||
todo_wine_if(v >= 9).
|
||||
ok(e === (v < 9 ? 0xa0005 : 0x0ffff) - 0x80000000, "[f.call(null, 'div')] e = " + e);
|
||||
|
||||
var elem1 = f.call(document, "div");
|
||||
var elem2 = f.call(document, "br");
|
||||
document.body.appendChild(elem1);
|
||||
document.body.appendChild(elem2);
|
||||
elem1.onclick = function() { ok(false, "unexpected elem1.onclick"); };
|
||||
var clicked = false;
|
||||
elem2.onclick = function() { clicked = true; };
|
||||
elem1.click.call(elem2);
|
||||
ok(clicked === true, "elem2.onclick not called");
|
||||
|
||||
elem1 = f.apply(document, ["div"]);
|
||||
elem2 = f.apply(document, ["br"]);
|
||||
document.body.appendChild(elem1);
|
||||
document.body.appendChild(elem2);
|
||||
elem1.onclick = function() { ok(false, "unexpected elem1.onclick"); };
|
||||
clicked = false;
|
||||
elem2.onclick = function() { clicked = true; };
|
||||
elem1.click.apply(elem2);
|
||||
ok(clicked === true, "elem2.onclick not called");
|
||||
|
||||
try {
|
||||
elem1.click.apply(elem2, { length: -1 });
|
||||
ok(false, "exception expected");
|
||||
}catch(ex) {}
|
||||
});
|
||||
|
||||
sync_test("elem_props", function() {
|
||||
var elem = document.documentElement;
|
||||
|
||||
|
|
|
@ -249,7 +249,7 @@ NTSTATUS WINAPI RtlWow64GetThreadSelectorEntry( HANDLE handle, THREAD_DESCRIPTOR
|
|||
{
|
||||
/* hardcoded values */
|
||||
#ifdef __arm64ec__
|
||||
context.SegCs = 0x33;
|
||||
context.SegCs = 0x23;
|
||||
context.SegSs = 0x2b;
|
||||
context.SegFs = 0x53;
|
||||
#elif defined(__x86_64__)
|
||||
|
|
|
@ -341,20 +341,19 @@ static NTSTATUS RTL_ReportRegistryValue(PKEY_VALUE_FULL_INFORMATION pInfo,
|
|||
pInfo->DataLength);
|
||||
else
|
||||
{
|
||||
if (bin[0] <= sizeof(ULONG))
|
||||
if (bin[0] < 0)
|
||||
{
|
||||
memcpy(&bin[1], ((CHAR*)pInfo) + pInfo->DataOffset,
|
||||
min(-bin[0], pInfo->DataLength));
|
||||
if (pInfo->DataLength <= -bin[0])
|
||||
memcpy(bin, (char*)pInfo + pInfo->DataOffset, pInfo->DataLength);
|
||||
}
|
||||
else
|
||||
else if (pInfo->DataLength <= bin[0])
|
||||
{
|
||||
len = min(bin[0], pInfo->DataLength);
|
||||
bin[1] = len;
|
||||
bin[2] = pInfo->Type;
|
||||
memcpy(&bin[3], ((CHAR*)pInfo) + pInfo->DataOffset, len);
|
||||
bin[0] = len;
|
||||
bin[1] = pInfo->Type;
|
||||
memcpy(bin + 2, (char*)pInfo + pInfo->DataOffset, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (pQuery->QueryRoutine)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2553,6 +2553,7 @@ struct query_reg_values_test
|
|||
ULONG expected_type;
|
||||
const WCHAR *expected_data;
|
||||
ULONG expected_data_size;
|
||||
ULONG size_limit;
|
||||
};
|
||||
|
||||
static unsigned int query_routine_calls;
|
||||
|
@ -2625,6 +2626,23 @@ static NTSTATUS WINAPI query_routine(const WCHAR *value_name, ULONG value_type,
|
|||
|
||||
static UNICODE_STRING query_reg_values_direct_str;
|
||||
|
||||
static ULONG query_reg_values_direct_int;
|
||||
|
||||
static union
|
||||
{
|
||||
ULONG size;
|
||||
char data[16];
|
||||
}
|
||||
query_reg_values_direct_sized;
|
||||
|
||||
static struct
|
||||
{
|
||||
ULONG size;
|
||||
ULONG type;
|
||||
char data[16];
|
||||
}
|
||||
query_reg_values_direct_typed;
|
||||
|
||||
static struct query_reg_values_test query_reg_values_tests[] =
|
||||
{
|
||||
/* Empty table */
|
||||
|
@ -2644,7 +2662,7 @@ static struct query_reg_values_test query_reg_values_tests[] =
|
|||
/* The query routine is called for every value in current key */
|
||||
{
|
||||
{{ query_routine }},
|
||||
STATUS_SUCCESS, 4, SKIP_NAME_CHECK | SKIP_DATA_CHECK
|
||||
STATUS_SUCCESS, 6, SKIP_NAME_CHECK | SKIP_DATA_CHECK
|
||||
},
|
||||
/* NOVALUE is ignored when the name is not null */
|
||||
{
|
||||
|
@ -2678,6 +2696,26 @@ static struct query_reg_values_test query_reg_values_tests[] =
|
|||
&query_reg_values_direct_str }},
|
||||
STATUS_SUCCESS, 0, 0, REG_SZ, L"%SYSTEMDRIVE%"
|
||||
},
|
||||
{
|
||||
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"MeaningOfLife32", &query_reg_values_direct_int }},
|
||||
STATUS_SUCCESS, 0, 0, REG_DWORD, (WCHAR*)42
|
||||
},
|
||||
{
|
||||
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"MeaningOfLife64", &query_reg_values_direct_sized }},
|
||||
STATUS_SUCCESS, 0, 0, REG_NONE, L"\x2a\0\0", sizeof(UINT64)
|
||||
},
|
||||
{
|
||||
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"MeaningOfLife64", &query_reg_values_direct_sized }},
|
||||
STATUS_SUCCESS, 0, 0, REG_NONE, L"\xff", 1, 1
|
||||
},
|
||||
{
|
||||
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"MeaningOfLife64", &query_reg_values_direct_typed }},
|
||||
STATUS_SUCCESS, 0, 0, REG_QWORD, L"\x2a\0\0", sizeof(UINT64)
|
||||
},
|
||||
{
|
||||
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"MeaningOfLife64", &query_reg_values_direct_typed }},
|
||||
STATUS_SUCCESS, 0, 0, 0x23, L"\x23", 1, 1
|
||||
},
|
||||
/* DIRECT on a multi-string crashes on Windows without NOEXPAND */
|
||||
/* {
|
||||
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"CapitalsOfEurope", &query_reg_values_direct_str }},
|
||||
|
@ -2783,8 +2821,8 @@ static struct query_reg_values_test query_reg_values_tests[] =
|
|||
/* DIRECT additionally requires the default value to be a string */
|
||||
{
|
||||
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
|
||||
&query_reg_values_direct_str, REG_DWORD, (WCHAR*)0xdeadbeef }},
|
||||
STATUS_SUCCESS, 0, 0, REG_NONE, NULL, -1
|
||||
&query_reg_values_direct_int, REG_DWORD, (WCHAR*)0xdeadbeef }},
|
||||
STATUS_SUCCESS, 0
|
||||
},
|
||||
/* REQUIRED fails if the value doesn't exist and there is no default */
|
||||
{
|
||||
|
@ -2821,8 +2859,16 @@ static void test_RtlQueryRegistryValues(void)
|
|||
L"Brussels\0Paris\0%PATH%", sizeof(L"Brussels\0Paris\0%PATH%"));
|
||||
ok(status == ERROR_SUCCESS, "Failed to create registry value CapitalsOfEurope: %lu\n", status);
|
||||
|
||||
status = RegSetKeyValueW(HKEY_CURRENT_USER, L"WineTest", L"MeaningOfLife32", REG_DWORD,
|
||||
L"\x2a", sizeof(DWORD));
|
||||
ok(status == ERROR_SUCCESS, "Failed to create registry value MeaningOfLife32: %lu\n", status);
|
||||
|
||||
status = RegSetKeyValueW(HKEY_CURRENT_USER, L"WineTest", L"MeaningOfLife64", REG_QWORD,
|
||||
L"\x2a\0\0", sizeof(UINT64));
|
||||
ok(status == ERROR_SUCCESS, "Failed to create registry value MeaningOfLife64: %lu\n", status);
|
||||
|
||||
status = RegSetKeyValueW(HKEY_CURRENT_USER, L"WineTest\\subkey", L"Color", REG_SZ,
|
||||
(void*)L"Yellow", sizeof(L"Yellow"));
|
||||
L"Yellow", sizeof(L"Yellow"));
|
||||
ok(status == ERROR_SUCCESS, "Failed to create registry value Color: %lu\n", status);
|
||||
|
||||
query_reg_values_direct_str.MaximumLength = 32 * sizeof(WCHAR);
|
||||
|
@ -2846,10 +2892,22 @@ static void test_RtlQueryRegistryValues(void)
|
|||
}
|
||||
|
||||
query_routine_calls = 0;
|
||||
|
||||
query_reg_values_direct_str.Length = query_reg_values_direct_str.MaximumLength - sizeof(WCHAR);
|
||||
memset(query_reg_values_direct_str.Buffer, 0x23, query_reg_values_direct_str.Length);
|
||||
query_reg_values_direct_str.Buffer[query_reg_values_direct_str.Length] = 0;
|
||||
|
||||
query_reg_values_direct_int = 1;
|
||||
|
||||
memset(query_reg_values_direct_sized.data, 0x23, sizeof(query_reg_values_direct_sized));
|
||||
query_reg_values_direct_sized.size = test->size_limit ? -test->size_limit
|
||||
: -(LONG)sizeof(query_reg_values_direct_sized);
|
||||
|
||||
query_reg_values_direct_typed.size = test->size_limit ? test->size_limit
|
||||
: sizeof(query_reg_values_direct_typed.data);
|
||||
query_reg_values_direct_typed.type = 0x23;
|
||||
memset(query_reg_values_direct_typed.data, 0x23, sizeof(query_reg_values_direct_typed.data));
|
||||
|
||||
status = pRtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer, test->query_table, test, NULL);
|
||||
|
||||
todo_wine_if(test->flags & WINE_TODO_RET)
|
||||
|
@ -2877,22 +2935,54 @@ static void test_RtlQueryRegistryValues(void)
|
|||
expected_size = test->expected_data_size;
|
||||
}
|
||||
|
||||
if (!expected_size && expected_data && (expected_type == REG_SZ || expected_type == REG_EXPAND_SZ))
|
||||
expected_size = (wcslen(expected_data) + 1) * sizeof(WCHAR);
|
||||
else if (expected_size == -1)
|
||||
expected_size = query_reg_values_direct_str.MaximumLength;
|
||||
|
||||
todo_wine_if(test->flags & WINE_TODO_SIZE)
|
||||
ok(query_reg_values_direct_str.Length + sizeof(WCHAR) == expected_size,
|
||||
"Expected size %lu, got %Iu\n", expected_size,
|
||||
query_reg_values_direct_str.Length + sizeof(WCHAR));
|
||||
|
||||
if (expected_data)
|
||||
if (query->EntryContext == &query_reg_values_direct_str)
|
||||
{
|
||||
todo_wine_if(test->flags & WINE_TODO_DATA)
|
||||
ok(!memcmp(query_reg_values_direct_str.Buffer, expected_data, expected_size),
|
||||
"Expected data %s, got %s\n", debugstr_w(expected_data),
|
||||
debugstr_w(query_reg_values_direct_str.Buffer));
|
||||
if (!expected_size && expected_data)
|
||||
expected_size = (wcslen(expected_data) + 1) * sizeof(WCHAR);
|
||||
else if (expected_size == -1)
|
||||
expected_size = query_reg_values_direct_str.MaximumLength;
|
||||
|
||||
todo_wine_if(test->flags & WINE_TODO_SIZE)
|
||||
ok(query_reg_values_direct_str.Length + sizeof(WCHAR) == expected_size,
|
||||
"Expected size %lu, got %Iu\n", expected_size,
|
||||
query_reg_values_direct_str.Length + sizeof(WCHAR));
|
||||
|
||||
if (expected_data)
|
||||
{
|
||||
todo_wine_if(test->flags & WINE_TODO_DATA)
|
||||
ok(!memcmp(query_reg_values_direct_str.Buffer, expected_data, expected_size),
|
||||
"Expected data %s, got %s\n", debugstr_w(expected_data),
|
||||
debugstr_w(query_reg_values_direct_str.Buffer));
|
||||
}
|
||||
}
|
||||
else if (query->EntryContext == &query_reg_values_direct_int)
|
||||
{
|
||||
if (expected_data)
|
||||
{
|
||||
ok(!memcmp(&query_reg_values_direct_int, &expected_data, expected_size),
|
||||
"Data does not match\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
- ok(query_reg_values_direct_int == 1,
|
||||
"Expected data to not change, got %lu\n", query_reg_values_direct_int);
|
||||
}
|
||||
}
|
||||
else if (query->EntryContext == &query_reg_values_direct_sized)
|
||||
{
|
||||
ok(!memcmp(query_reg_values_direct_sized.data, expected_data, expected_size),
|
||||
"Data does not match\n");
|
||||
}
|
||||
else if (query->EntryContext == &query_reg_values_direct_typed)
|
||||
{
|
||||
ok(query_reg_values_direct_typed.size == expected_size,
|
||||
"Expected size %lu, got %lu\n", expected_size, query_reg_values_direct_typed.size);
|
||||
|
||||
ok(query_reg_values_direct_typed.type == expected_type,
|
||||
"Expected type %lu, got %lu\n", expected_type, query_reg_values_direct_typed.type);
|
||||
|
||||
ok(!memcmp(query_reg_values_direct_typed.data, expected_data, expected_size),
|
||||
"Data does not match\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1252,9 +1252,9 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
|
|||
|
||||
"5:\tmovw r0, #0x000d\n\t" /* STATUS_INVALID_PARAMETER */
|
||||
"movt r0, #0xc000\n\t"
|
||||
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t"
|
||||
".globl " __ASM_NAME("__wine_syscall_dispatcher_return") "\n"
|
||||
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
|
||||
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
|
||||
|
||||
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher_return,
|
||||
"mov r8, r0\n\t"
|
||||
"mov r0, r1\n\t"
|
||||
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
|
||||
|
|
|
@ -1607,9 +1607,9 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
|
|||
"ret x16\n"
|
||||
"4:\tmov x0, #0xc0000000\n\t" /* STATUS_INVALID_PARAMETER */
|
||||
"movk x0, #0x000d\n\t"
|
||||
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t"
|
||||
".globl " __ASM_NAME("__wine_syscall_dispatcher_return") "\n"
|
||||
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
|
||||
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
|
||||
|
||||
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher_return,
|
||||
"mov sp, x0\n\t"
|
||||
"mov x0, x1\n\t"
|
||||
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
|
||||
|
|
|
@ -2768,10 +2768,9 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
|
|||
__ASM_CFI("\t.cfi_restore_state\n")
|
||||
|
||||
"6:\tmovl $0xc000000d,%eax\n\t" /* STATUS_INVALID_PARAMETER */
|
||||
"jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t"
|
||||
"jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
|
||||
|
||||
".globl " __ASM_NAME("__wine_syscall_dispatcher_return") "\n"
|
||||
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
|
||||
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher_return,
|
||||
"movl 8(%esp),%eax\n\t"
|
||||
"movl 4(%esp),%esp\n\t"
|
||||
"jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
|
||||
|
|
|
@ -2876,9 +2876,9 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
|
|||
__ASM_CFI("\t.cfi_restore_state\n")
|
||||
"5:\tmovl $0xc000000d,%eax\n\t" /* STATUS_INVALID_PARAMETER */
|
||||
"movq %rsp,%rcx\n\t"
|
||||
"jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t"
|
||||
".globl " __ASM_NAME("__wine_syscall_dispatcher_return") "\n"
|
||||
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
|
||||
"jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
|
||||
|
||||
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher_return,
|
||||
"movq %rdi,%rcx\n\t"
|
||||
"movl 0xb0(%rcx),%r14d\n\t" /* frame->syscall_flags */
|
||||
"movq %rsi,%rax\n\t"
|
||||
|
|
|
@ -3621,6 +3621,7 @@ static TEB *init_teb( void *ptr, BOOL is_wow )
|
|||
if (is_wow) teb64->WowTebOffset = teb_offset;
|
||||
#else
|
||||
teb = (TEB *)teb32;
|
||||
teb32->Tib.ExceptionList = ~0u;
|
||||
teb64->Peb = PtrToUlong( (char *)peb - page_size );
|
||||
teb64->Tib.Self = PtrToUlong( teb64 );
|
||||
teb64->Tib.ExceptionList = PtrToUlong( teb32 );
|
||||
|
@ -3639,7 +3640,6 @@ static TEB *init_teb( void *ptr, BOOL is_wow )
|
|||
#endif
|
||||
teb->Peb = peb;
|
||||
teb->Tib.Self = &teb->Tib;
|
||||
teb->Tib.ExceptionList = (void *)~0ul;
|
||||
teb->Tib.StackBase = (void *)~0ul;
|
||||
teb->ActivationContextStackPointer = &teb->ActivationContextStack;
|
||||
InitializeListHead( &teb->ActivationContextStack.FrameListCache );
|
||||
|
|
|
@ -65,7 +65,6 @@ static PFN_vkGetPhysicalDeviceMemoryProperties2KHR pvkGetPhysicalDeviceMemoryPro
|
|||
static PFN_vkGetPhysicalDeviceMemoryProperties pvkGetPhysicalDeviceMemoryProperties;
|
||||
static PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR;
|
||||
static PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices;
|
||||
static const struct vulkan_funcs *vulkan_funcs;
|
||||
|
||||
static void d3dkmt_init_vulkan(void)
|
||||
{
|
||||
|
@ -94,7 +93,6 @@ static void d3dkmt_init_vulkan(void)
|
|||
if ((vr = p_vkCreateInstance( &create_info, NULL, &d3dkmt_vk_instance )))
|
||||
{
|
||||
WARN( "Failed to create a Vulkan instance, vr %d.\n", vr );
|
||||
vulkan_funcs = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -104,7 +102,7 @@ static void d3dkmt_init_vulkan(void)
|
|||
{ \
|
||||
WARN( "Failed to load " #f ".\n" ); \
|
||||
p_vkDestroyInstance( d3dkmt_vk_instance, NULL ); \
|
||||
vulkan_funcs = NULL; \
|
||||
d3dkmt_vk_instance = NULL; \
|
||||
return; \
|
||||
}
|
||||
LOAD_VK_FUNC( vkEnumeratePhysicalDevices )
|
||||
|
@ -118,7 +116,7 @@ static BOOL d3dkmt_use_vulkan(void)
|
|||
{
|
||||
static pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||
pthread_once( &once, d3dkmt_init_vulkan );
|
||||
return !!vulkan_funcs;
|
||||
return !!d3dkmt_vk_instance;
|
||||
}
|
||||
|
||||
/* d3dkmt_lock must be held */
|
||||
|
|
|
@ -740,22 +740,22 @@ BOOL WINAPI NtUserSetCursorPos( INT x, INT y )
|
|||
*/
|
||||
BOOL get_cursor_pos( POINT *pt )
|
||||
{
|
||||
struct object_lock lock = OBJECT_LOCK_INIT;
|
||||
const desktop_shm_t *desktop_shm;
|
||||
BOOL ret;
|
||||
DWORD last_change;
|
||||
DWORD last_change = 0;
|
||||
NTSTATUS status;
|
||||
UINT dpi;
|
||||
|
||||
if (!pt) return FALSE;
|
||||
|
||||
SERVER_START_REQ( set_cursor )
|
||||
while ((status = get_shared_desktop( &lock, &desktop_shm )) == STATUS_PENDING)
|
||||
{
|
||||
if ((ret = !wine_server_call( req )))
|
||||
{
|
||||
pt->x = reply->new_x;
|
||||
pt->y = reply->new_y;
|
||||
last_change = reply->last_change;
|
||||
}
|
||||
pt->x = desktop_shm->cursor.x;
|
||||
pt->y = desktop_shm->cursor.y;
|
||||
last_change = desktop_shm->cursor.last_change;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
ret = !status;
|
||||
|
||||
/* query new position from graphics driver if we haven't updated recently */
|
||||
if (ret && NtGetTickCount() - last_change > 100) ret = user_driver->pGetCursorPos( pt );
|
||||
|
|
|
@ -124,6 +124,7 @@ struct user_thread_info
|
|||
UINT spy_indent; /* Current spy indent */
|
||||
BOOL clipping_cursor; /* thread is currently clipping */
|
||||
DWORD clipping_reset; /* time when clipping was last reset */
|
||||
struct session_thread_data *session_data; /* shared session thread data */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof(struct user_thread_info) <= sizeof(((TEB *)0)->Win32ClientInfo) );
|
||||
|
|
|
@ -6340,6 +6340,7 @@ static void thread_detach(void)
|
|||
|
||||
cleanup_imm_thread();
|
||||
NtClose( thread_info->server_queue );
|
||||
free( thread_info->session_data );
|
||||
|
||||
exiting_thread_id = 0;
|
||||
}
|
||||
|
|
|
@ -205,6 +205,22 @@ extern void free_vulkan_gpu( struct vulkan_gpu *gpu );
|
|||
extern BOOL get_vulkan_uuid_from_luid( const LUID *luid, GUID *uuid );
|
||||
|
||||
/* winstation.c */
|
||||
|
||||
struct object_lock
|
||||
{
|
||||
UINT64 id;
|
||||
UINT64 seq;
|
||||
};
|
||||
#define OBJECT_LOCK_INIT {0}
|
||||
|
||||
/* Get shared session object's data pointer, must be called in a loop while STATUS_PENDING
|
||||
* is returned, lock must be initialized with OBJECT_LOCK_INIT.
|
||||
*
|
||||
* The data read from the objects may be transient and no logic should be executed based
|
||||
* on it, within the loop, or after, unless the function has returned STATUS_SUCCESS.
|
||||
*/
|
||||
extern NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **desktop_shm );
|
||||
|
||||
extern BOOL is_virtual_desktop(void);
|
||||
|
||||
/* window.c */
|
||||
|
|
|
@ -22,9 +22,14 @@
|
|||
#pragma makedep unix
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include <stdarg.h>
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "ntuser.h"
|
||||
|
@ -40,6 +45,180 @@ WINE_DECLARE_DEBUG_CHANNEL(win);
|
|||
|
||||
#define DESKTOP_ALL_ACCESS 0x01ff
|
||||
|
||||
struct session_thread_data
|
||||
{
|
||||
const shared_object_t *shared_desktop; /* thread desktop shared session cached object */
|
||||
};
|
||||
|
||||
struct session_block
|
||||
{
|
||||
struct list entry; /* entry in the session block list */
|
||||
const char *data; /* base pointer for the mmaped data */
|
||||
SIZE_T offset; /* offset of data in the session shared mapping */
|
||||
SIZE_T size; /* size of the mmaped data */
|
||||
};
|
||||
|
||||
static pthread_mutex_t session_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct list session_blocks = LIST_INIT(session_blocks);
|
||||
|
||||
static struct session_thread_data *get_session_thread_data(void)
|
||||
{
|
||||
struct user_thread_info *thread_info = get_user_thread_info();
|
||||
if (!thread_info->session_data) thread_info->session_data = calloc(1, sizeof(*thread_info->session_data));
|
||||
return thread_info->session_data;
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/* this prevents compilers from incorrectly reordering non-volatile reads (e.g., memcpy) from shared memory */
|
||||
#define __SHARED_READ_FENCE do { __asm__ __volatile__( "" ::: "memory" ); } while (0)
|
||||
#else
|
||||
#define __SHARED_READ_FENCE __atomic_thread_fence( __ATOMIC_ACQUIRE )
|
||||
#endif
|
||||
|
||||
static void shared_object_acquire_seqlock( const shared_object_t *object, UINT64 *seq )
|
||||
{
|
||||
while ((*seq = ReadNoFence64( &object->seq )) & 1) YieldProcessor();
|
||||
__SHARED_READ_FENCE;
|
||||
}
|
||||
|
||||
static BOOL shared_object_release_seqlock( const shared_object_t *object, UINT64 seq )
|
||||
{
|
||||
__SHARED_READ_FENCE;
|
||||
return ReadNoFence64( &object->seq ) == seq;
|
||||
}
|
||||
|
||||
static object_id_t shared_object_get_id( const shared_object_t *object )
|
||||
{
|
||||
struct object_lock lock = OBJECT_LOCK_INIT;
|
||||
do
|
||||
{
|
||||
shared_object_acquire_seqlock( object, &lock.seq );
|
||||
lock.id = object->id;
|
||||
} while (!shared_object_release_seqlock( object, lock.seq ));
|
||||
return lock.id;
|
||||
}
|
||||
|
||||
static NTSTATUS map_shared_session_block( SIZE_T offset, SIZE_T size, struct session_block **ret )
|
||||
{
|
||||
static const WCHAR nameW[] =
|
||||
{
|
||||
'\\','K','e','r','n','e','l','O','b','j','e','c','t','s','\\',
|
||||
'_','_','w','i','n','e','_','s','e','s','s','i','o','n',0
|
||||
};
|
||||
UNICODE_STRING name = RTL_CONSTANT_STRING( nameW );
|
||||
LARGE_INTEGER off = {.QuadPart = offset - (offset % system_info.AllocationGranularity)};
|
||||
struct session_block *block;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
unsigned int status;
|
||||
HANDLE handle;
|
||||
|
||||
assert( offset + size > offset );
|
||||
|
||||
if (!(block = calloc( 1, sizeof(*block) ))) return STATUS_NO_MEMORY;
|
||||
|
||||
InitializeObjectAttributes( &attr, &name, 0, NULL, NULL );
|
||||
if ((status = NtOpenSection( &handle, SECTION_MAP_READ, &attr )))
|
||||
WARN( "Failed to open shared session section, status %#x\n", status );
|
||||
else
|
||||
{
|
||||
if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), (void **)&block->data, 0, 0,
|
||||
&off, &block->size, ViewUnmap, 0, PAGE_READONLY )))
|
||||
WARN( "Failed to map shared session block, status %#x\n", status );
|
||||
else
|
||||
{
|
||||
list_add_tail( &session_blocks, &block->entry );
|
||||
block->offset = off.QuadPart;
|
||||
assert( block->offset + block->size > block->offset );
|
||||
}
|
||||
NtClose( handle );
|
||||
}
|
||||
|
||||
if (status) free( block );
|
||||
else *ret = block;
|
||||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS find_shared_session_block( SIZE_T offset, SIZE_T size, struct session_block **ret )
|
||||
{
|
||||
struct session_block *block;
|
||||
UINT status;
|
||||
|
||||
assert( offset + size > offset );
|
||||
|
||||
pthread_mutex_lock( &session_lock );
|
||||
|
||||
LIST_FOR_EACH_ENTRY( block, &session_blocks, struct session_block, entry )
|
||||
{
|
||||
if (block->offset < offset && offset + size <= block->offset + block->size)
|
||||
{
|
||||
*ret = block;
|
||||
pthread_mutex_unlock( &session_lock );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if ((status = map_shared_session_block( offset, size, ret )))
|
||||
{
|
||||
WARN( "Failed to map session block for offset %s, size %s, status %#x\n",
|
||||
wine_dbgstr_longlong(offset), wine_dbgstr_longlong(size), status );
|
||||
}
|
||||
|
||||
pthread_mutex_unlock( &session_lock );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static const shared_object_t *find_shared_session_object( obj_locator_t locator )
|
||||
{
|
||||
const shared_object_t *object;
|
||||
struct session_block *block;
|
||||
NTSTATUS status;
|
||||
|
||||
if (locator.id && !(status = find_shared_session_block( locator.offset, sizeof(*object), &block )))
|
||||
{
|
||||
object = (const shared_object_t *)(block->data + locator.offset - block->offset);
|
||||
if (locator.id == shared_object_get_id( object )) return object;
|
||||
WARN( "Session object id doesn't match expected id %s\n", wine_dbgstr_longlong(locator.id) );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **desktop_shm )
|
||||
{
|
||||
struct session_thread_data *data = get_session_thread_data();
|
||||
const shared_object_t *object;
|
||||
|
||||
TRACE( "lock %p, desktop_shm %p\n", lock, desktop_shm );
|
||||
|
||||
if (!(object = data->shared_desktop))
|
||||
{
|
||||
obj_locator_t locator;
|
||||
|
||||
SERVER_START_REQ( get_thread_desktop )
|
||||
{
|
||||
req->tid = GetCurrentThreadId();
|
||||
wine_server_call( req );
|
||||
locator = reply->locator;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
data->shared_desktop = find_shared_session_object( locator );
|
||||
if (!(object = data->shared_desktop)) return STATUS_INVALID_HANDLE;
|
||||
memset( lock, 0, sizeof(*lock) );
|
||||
}
|
||||
|
||||
if (!lock->id || !shared_object_release_seqlock( object, lock->seq ))
|
||||
{
|
||||
shared_object_acquire_seqlock( object, &lock->seq );
|
||||
*desktop_shm = &object->shm.desktop;
|
||||
lock->id = object->id;
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL is_virtual_desktop(void)
|
||||
{
|
||||
HANDLE desktop = NtUserGetThreadDesktop( GetCurrentThreadId() );
|
||||
|
@ -249,11 +428,13 @@ HDESK WINAPI NtUserGetThreadDesktop( DWORD thread )
|
|||
BOOL WINAPI NtUserSetThreadDesktop( HDESK handle )
|
||||
{
|
||||
BOOL ret, was_virtual_desktop = is_virtual_desktop();
|
||||
obj_locator_t locator;
|
||||
|
||||
SERVER_START_REQ( set_thread_desktop )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
ret = !wine_server_call_err( req );
|
||||
locator = reply->locator;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -261,6 +442,7 @@ BOOL WINAPI NtUserSetThreadDesktop( HDESK handle )
|
|||
{
|
||||
struct user_thread_info *thread_info = get_user_thread_info();
|
||||
struct user_key_state_info *key_state_info = thread_info->key_state;
|
||||
get_session_thread_data()->shared_desktop = find_shared_session_object( locator );
|
||||
thread_info->client_info.top_window = 0;
|
||||
thread_info->client_info.msg_window = 0;
|
||||
if (key_state_info) key_state_info->time = 0;
|
||||
|
|
|
@ -19,6 +19,7 @@ SOURCES = \
|
|||
rsrc.rc \
|
||||
unixlib.c \
|
||||
video_decoder.c \
|
||||
video_encoder.c \
|
||||
video_processor.c \
|
||||
wg_allocator.c \
|
||||
wg_format.c \
|
||||
|
|
|
@ -167,6 +167,8 @@ HRESULT aac_decoder_create(REFIID riid, void **ret);
|
|||
HRESULT h264_decoder_create(REFIID riid, void **ret);
|
||||
HRESULT video_processor_create(REFIID riid, void **ret);
|
||||
|
||||
HRESULT h264_encoder_create(REFIID riid, void **ret);
|
||||
|
||||
extern const GUID MFAudioFormat_RAW_AAC;
|
||||
|
||||
#endif /* __GST_PRIVATE_INCLUDED__ */
|
||||
|
|
|
@ -133,6 +133,7 @@ class_objects[] =
|
|||
{ &CLSID_GStreamerByteStreamHandler, &gstreamer_byte_stream_handler_create },
|
||||
{ &CLSID_MSAACDecMFT, &aac_decoder_create },
|
||||
{ &CLSID_MSH264DecoderMFT, &h264_decoder_create },
|
||||
{ &CLSID_MSH264EncoderMFT, &h264_encoder_create },
|
||||
};
|
||||
|
||||
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
|
@ -208,6 +209,18 @@ HRESULT mfplat_DllRegisterServer(void)
|
|||
{MFMediaType_Video, MFVideoFormat_YUY2},
|
||||
};
|
||||
|
||||
MFT_REGISTER_TYPE_INFO h264_encoder_input_types[] =
|
||||
{
|
||||
{MFMediaType_Video, MFVideoFormat_IYUV},
|
||||
{MFMediaType_Video, MFVideoFormat_YV12},
|
||||
{MFMediaType_Video, MFVideoFormat_NV12},
|
||||
{MFMediaType_Video, MFVideoFormat_YUY2},
|
||||
};
|
||||
MFT_REGISTER_TYPE_INFO h264_encoder_output_types[] =
|
||||
{
|
||||
{MFMediaType_Video, MFVideoFormat_H264},
|
||||
};
|
||||
|
||||
MFT_REGISTER_TYPE_INFO video_processor_input_types[] =
|
||||
{
|
||||
{MFMediaType_Video, MFVideoFormat_IYUV},
|
||||
|
@ -371,6 +384,16 @@ HRESULT mfplat_DllRegisterServer(void)
|
|||
ARRAY_SIZE(h264_decoder_output_types),
|
||||
h264_decoder_output_types,
|
||||
},
|
||||
{
|
||||
CLSID_MSH264EncoderMFT,
|
||||
MFT_CATEGORY_VIDEO_ENCODER,
|
||||
L"H264 Encoder MFT",
|
||||
MFT_ENUM_FLAG_SYNCMFT,
|
||||
ARRAY_SIZE(h264_encoder_input_types),
|
||||
h264_encoder_input_types,
|
||||
ARRAY_SIZE(h264_encoder_output_types),
|
||||
h264_encoder_output_types,
|
||||
},
|
||||
{
|
||||
CLSID_WMVDecoderMFT,
|
||||
MFT_CATEGORY_VIDEO_DECODER,
|
||||
|
|
338
dlls/winegstreamer/video_encoder.c
Normal file
338
dlls/winegstreamer/video_encoder.c
Normal file
|
@ -0,0 +1,338 @@
|
|||
/* Generic Video Encoder Transform
|
||||
*
|
||||
* Copyright 2024 Ziqing Hui 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 "gst_private.h"
|
||||
|
||||
#include "mfapi.h"
|
||||
#include "mferror.h"
|
||||
#include "mfobjects.h"
|
||||
#include "mftransform.h"
|
||||
#include "mediaerr.h"
|
||||
#include "wmcodecdsp.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
#include "initguid.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
||||
|
||||
struct video_encoder
|
||||
{
|
||||
IMFTransform IMFTransform_iface;
|
||||
LONG refcount;
|
||||
|
||||
IMFAttributes *attributes;
|
||||
};
|
||||
|
||||
static inline struct video_encoder *impl_from_IMFTransform(IMFTransform *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct video_encoder, IMFTransform_iface);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out)
|
||||
{
|
||||
struct video_encoder *encoder = impl_from_IMFTransform(iface);
|
||||
|
||||
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
|
||||
|
||||
if (IsEqualGUID(iid, &IID_IMFTransform) || IsEqualGUID(iid, &IID_IUnknown))
|
||||
*out = &encoder->IMFTransform_iface;
|
||||
else
|
||||
{
|
||||
*out = NULL;
|
||||
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
IUnknown_AddRef((IUnknown *)*out);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ULONG WINAPI transform_AddRef(IMFTransform *iface)
|
||||
{
|
||||
struct video_encoder *encoder = impl_from_IMFTransform(iface);
|
||||
ULONG refcount = InterlockedIncrement(&encoder->refcount);
|
||||
|
||||
TRACE("iface %p increasing refcount to %lu.\n", encoder, refcount);
|
||||
|
||||
return refcount;
|
||||
}
|
||||
|
||||
static ULONG WINAPI transform_Release(IMFTransform *iface)
|
||||
{
|
||||
struct video_encoder *encoder = impl_from_IMFTransform(iface);
|
||||
ULONG refcount = InterlockedDecrement(&encoder->refcount);
|
||||
|
||||
TRACE("iface %p decreasing refcount to %lu.\n", encoder, refcount);
|
||||
|
||||
if (!refcount)
|
||||
{
|
||||
IMFAttributes_Release(encoder->attributes);
|
||||
free(encoder);
|
||||
}
|
||||
|
||||
return refcount;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum,
|
||||
DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum)
|
||||
{
|
||||
TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
|
||||
iface, input_minimum, input_maximum, output_minimum, output_maximum);
|
||||
*input_minimum = *input_maximum = *output_minimum = *output_maximum = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
|
||||
{
|
||||
TRACE("iface %p, inputs %p, outputs %p.\n", iface, inputs, outputs);
|
||||
*inputs = *outputs = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
|
||||
DWORD output_size, DWORD *outputs)
|
||||
{
|
||||
FIXME("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface,
|
||||
input_size, inputs, output_size, outputs);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, info %p.\n", iface, id, info);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, info %p.\n", iface, id, info);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
|
||||
{
|
||||
struct video_encoder *encoder = impl_from_IMFTransform(iface);
|
||||
|
||||
TRACE("iface %p, attributes %p.\n", iface, attributes);
|
||||
|
||||
if (!attributes)
|
||||
return E_POINTER;
|
||||
|
||||
IMFAttributes_AddRef((*attributes = encoder->attributes));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, attributes %p.\n", iface, id, attributes);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, attributes %p.\n", iface, id, attributes);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id)
|
||||
{
|
||||
FIXME("iface %p, id %#lx.\n", iface, id);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
|
||||
{
|
||||
FIXME("iface %p, streams %lu, ids %p.\n", iface, streams, ids);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
|
||||
IMFMediaType **type)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id,
|
||||
DWORD index, IMFMediaType **type)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, type %p\n", iface, id, type);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, type %p\n", iface, id, type);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, flags %p.\n", iface, id, flags);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_GetOutputStatus(IMFTransform *iface, DWORD *flags)
|
||||
{
|
||||
FIXME("iface %p, flags %p stub!\n", iface, flags);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
|
||||
{
|
||||
FIXME("iface %p, lower %I64d, upper %I64d.\n", iface, lower, upper);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, event %p stub!\n", iface, id, event);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
|
||||
{
|
||||
FIXME("iface %p, message %#x, param %Ix.\n", iface, message, param);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
|
||||
{
|
||||
FIXME("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
|
||||
MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
|
||||
{
|
||||
FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static const IMFTransformVtbl transform_vtbl =
|
||||
{
|
||||
transform_QueryInterface,
|
||||
transform_AddRef,
|
||||
transform_Release,
|
||||
transform_GetStreamLimits,
|
||||
transform_GetStreamCount,
|
||||
transform_GetStreamIDs,
|
||||
transform_GetInputStreamInfo,
|
||||
transform_GetOutputStreamInfo,
|
||||
transform_GetAttributes,
|
||||
transform_GetInputStreamAttributes,
|
||||
transform_GetOutputStreamAttributes,
|
||||
transform_DeleteInputStream,
|
||||
transform_AddInputStreams,
|
||||
transform_GetInputAvailableType,
|
||||
transform_GetOutputAvailableType,
|
||||
transform_SetInputType,
|
||||
transform_SetOutputType,
|
||||
transform_GetInputCurrentType,
|
||||
transform_GetOutputCurrentType,
|
||||
transform_GetInputStatus,
|
||||
transform_GetOutputStatus,
|
||||
transform_SetOutputBounds,
|
||||
transform_ProcessEvent,
|
||||
transform_ProcessMessage,
|
||||
transform_ProcessInput,
|
||||
transform_ProcessOutput,
|
||||
};
|
||||
|
||||
static HRESULT video_encoder_create(struct video_encoder **out)
|
||||
{
|
||||
struct video_encoder *encoder;
|
||||
HRESULT hr;
|
||||
|
||||
if (!(encoder = calloc(1, sizeof(*encoder))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
encoder->IMFTransform_iface.lpVtbl = &transform_vtbl;
|
||||
encoder->refcount = 1;
|
||||
|
||||
if (FAILED(hr = MFCreateAttributes(&encoder->attributes, 16)))
|
||||
goto failed;
|
||||
if (FAILED(hr = IMFAttributes_SetUINT32(encoder->attributes, &MFT_ENCODER_SUPPORTS_CONFIG_EVENT, TRUE)))
|
||||
goto failed;
|
||||
|
||||
*out = encoder;
|
||||
TRACE("Created video encoder %p\n", encoder);
|
||||
return S_OK;
|
||||
|
||||
failed:
|
||||
if (encoder->attributes)
|
||||
IMFAttributes_Release(encoder->attributes);
|
||||
free(encoder);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT h264_encoder_create(REFIID riid, void **out)
|
||||
{
|
||||
const MFVIDEOFORMAT input_format =
|
||||
{
|
||||
.dwSize = sizeof(MFVIDEOFORMAT),
|
||||
.videoInfo = {.dwWidth = 1920, .dwHeight = 1080},
|
||||
.guidFormat = MFVideoFormat_NV12,
|
||||
};
|
||||
const MFVIDEOFORMAT output_format =
|
||||
{
|
||||
.dwSize = sizeof(MFVIDEOFORMAT),
|
||||
.videoInfo = {.dwWidth = 1920, .dwHeight = 1080},
|
||||
.guidFormat = MFVideoFormat_H264,
|
||||
};
|
||||
struct video_encoder *encoder;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("riid %s, out %p.\n", debugstr_guid(riid), out);
|
||||
|
||||
if (FAILED(hr = check_video_transform_support(&input_format, &output_format)))
|
||||
{
|
||||
ERR_(winediag)("GStreamer doesn't support H.264 encoding, please install appropriate plugins\n");
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (FAILED(hr = video_encoder_create(&encoder)))
|
||||
return hr;
|
||||
|
||||
TRACE("Created h264 encoder transform %p.\n", &encoder->IMFTransform_iface);
|
||||
|
||||
hr = IMFTransform_QueryInterface(&encoder->IMFTransform_iface, riid, out);
|
||||
IMFTransform_Release(&encoder->IMFTransform_iface);
|
||||
return hr;
|
||||
}
|
|
@ -107,6 +107,12 @@ coclass CWMVDecMediaObject {}
|
|||
]
|
||||
coclass CMSH264DecoderMFT {}
|
||||
|
||||
[
|
||||
threading(both),
|
||||
uuid(6ca50344-051a-4ded-9779-a43305165e35)
|
||||
]
|
||||
coclass CMSH264EncoderMFT {}
|
||||
|
||||
[
|
||||
threading(both),
|
||||
uuid(f447b69e-1884-4a7e-8055-346f74d6edb3)
|
||||
|
|
|
@ -48,9 +48,14 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
|||
#include "wine/vulkan.h"
|
||||
#include "wine/vulkan_driver.h"
|
||||
|
||||
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR)
|
||||
|
||||
static void *xrandr_handle;
|
||||
static void *vulkan_handle;
|
||||
static void *(*p_vkGetInstanceProcAddr)(VkInstance, const char *);
|
||||
|
||||
static VkInstance vk_instance; /* Vulkan instance for XRandR functions */
|
||||
static VkResult (*p_vkGetRandROutputDisplayEXT)( VkPhysicalDevice, Display *, RROutput, VkDisplayKHR * );
|
||||
static PFN_vkGetPhysicalDeviceProperties2KHR p_vkGetPhysicalDeviceProperties2KHR;
|
||||
static PFN_vkEnumeratePhysicalDevices p_vkEnumeratePhysicalDevices;
|
||||
|
||||
#define MAKE_FUNCPTR(f) static typeof(f) * p##f;
|
||||
MAKE_FUNCPTR(XRRConfigCurrentConfiguration)
|
||||
|
@ -140,8 +145,31 @@ sym_not_found:
|
|||
|
||||
#ifdef SONAME_LIBVULKAN
|
||||
|
||||
static void *vulkan_handle;
|
||||
static void *(*p_vkGetInstanceProcAddr)(VkInstance, const char *);
|
||||
|
||||
static void vulkan_init_once(void)
|
||||
{
|
||||
static const char *extensions[] =
|
||||
{
|
||||
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
|
||||
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
|
||||
"VK_EXT_acquire_xlib_display",
|
||||
"VK_EXT_direct_mode_display",
|
||||
"VK_KHR_display",
|
||||
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||
};
|
||||
VkInstanceCreateInfo create_info =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.ppEnabledExtensionNames = extensions,
|
||||
.enabledExtensionCount = ARRAY_SIZE(extensions),
|
||||
};
|
||||
|
||||
PFN_vkDestroyInstance p_vkDestroyInstance;
|
||||
PFN_vkCreateInstance p_vkCreateInstance;
|
||||
VkResult vr;
|
||||
|
||||
if (!(vulkan_handle = dlopen( SONAME_LIBVULKAN, RTLD_NOW )))
|
||||
{
|
||||
ERR( "Failed to load %s\n", SONAME_LIBVULKAN );
|
||||
|
@ -153,12 +181,33 @@ static void vulkan_init_once(void)
|
|||
{ \
|
||||
ERR( "Failed to find " #f "\n" ); \
|
||||
dlclose( vulkan_handle ); \
|
||||
vulkan_handle = NULL; \
|
||||
return; \
|
||||
}
|
||||
|
||||
LOAD_FUNCPTR( vkGetInstanceProcAddr );
|
||||
#undef LOAD_FUNCPTR
|
||||
|
||||
p_vkCreateInstance = p_vkGetInstanceProcAddr( NULL, "vkCreateInstance" );
|
||||
if ((vr = p_vkCreateInstance( &create_info, NULL, &vk_instance )))
|
||||
{
|
||||
WARN( "Failed to create a Vulkan instance, vr %d.\n", vr );
|
||||
return;
|
||||
}
|
||||
|
||||
p_vkDestroyInstance = p_vkGetInstanceProcAddr( vk_instance, "vkDestroyInstance" );
|
||||
#define LOAD_VK_FUNC(f) \
|
||||
if (!(p_##f = (void *)p_vkGetInstanceProcAddr( vk_instance, #f ))) \
|
||||
{ \
|
||||
WARN("Failed to load " #f ".\n"); \
|
||||
p_vkDestroyInstance( vk_instance, NULL ); \
|
||||
vk_instance = NULL; \
|
||||
return; \
|
||||
}
|
||||
|
||||
LOAD_VK_FUNC( vkEnumeratePhysicalDevices )
|
||||
LOAD_VK_FUNC( vkGetPhysicalDeviceProperties2KHR )
|
||||
LOAD_VK_FUNC( vkGetRandROutputDisplayEXT )
|
||||
#undef LOAD_VK_FUNC
|
||||
}
|
||||
|
||||
#else /* SONAME_LIBVULKAN */
|
||||
|
@ -174,7 +223,7 @@ static BOOL vulkan_init(void)
|
|||
{
|
||||
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
|
||||
pthread_once( &init_once, vulkan_init_once );
|
||||
return !!vulkan_handle;
|
||||
return !!vk_instance;
|
||||
}
|
||||
|
||||
static int XRandRErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
|
||||
|
@ -668,65 +717,20 @@ static BOOL is_crtc_primary( RECT primary, const XRRCrtcInfo *crtc )
|
|||
crtc->y + crtc->height == primary.bottom;
|
||||
}
|
||||
|
||||
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR)
|
||||
|
||||
static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRProviderInfo *provider_info,
|
||||
struct x11drv_gpu *prev_gpus, int prev_gpu_count )
|
||||
{
|
||||
static const char *extensions[] =
|
||||
{
|
||||
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
|
||||
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
|
||||
"VK_EXT_acquire_xlib_display",
|
||||
"VK_EXT_direct_mode_display",
|
||||
"VK_KHR_display",
|
||||
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||
};
|
||||
VkResult (*pvkGetRandROutputDisplayEXT)( VkPhysicalDevice, Display *, RROutput, VkDisplayKHR * );
|
||||
PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR;
|
||||
PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices;
|
||||
uint32_t device_count, device_idx, output_idx, i;
|
||||
PFN_vkDestroyInstance pvkDestroyInstance = NULL;
|
||||
VkPhysicalDevice *vk_physical_devices = NULL;
|
||||
VkPhysicalDeviceProperties2 properties2;
|
||||
PFN_vkCreateInstance pvkCreateInstance;
|
||||
VkInstanceCreateInfo create_info;
|
||||
VkPhysicalDeviceIDProperties id;
|
||||
VkInstance vk_instance = NULL;
|
||||
VkDisplayKHR vk_display;
|
||||
BOOL ret = FALSE;
|
||||
VkResult vr;
|
||||
|
||||
if (!vulkan_init()) goto done;
|
||||
|
||||
memset( &create_info, 0, sizeof(create_info) );
|
||||
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
create_info.enabledExtensionCount = ARRAY_SIZE(extensions);
|
||||
create_info.ppEnabledExtensionNames = extensions;
|
||||
|
||||
#define LOAD_VK_FUNC(f) \
|
||||
if (!(p##f = (void *)p_vkGetInstanceProcAddr( vk_instance, #f ))) \
|
||||
{ \
|
||||
WARN("Failed to load " #f ".\n"); \
|
||||
goto done; \
|
||||
}
|
||||
|
||||
LOAD_VK_FUNC( vkCreateInstance )
|
||||
|
||||
vr = pvkCreateInstance( &create_info, NULL, &vk_instance );
|
||||
if (vr != VK_SUCCESS)
|
||||
{
|
||||
WARN( "Failed to create a Vulkan instance, vr %d.\n", vr );
|
||||
goto done;
|
||||
}
|
||||
|
||||
LOAD_VK_FUNC(vkEnumeratePhysicalDevices)
|
||||
LOAD_VK_FUNC(vkGetPhysicalDeviceProperties2KHR)
|
||||
LOAD_VK_FUNC(vkGetRandROutputDisplayEXT)
|
||||
LOAD_VK_FUNC(vkDestroyInstance)
|
||||
#undef LOAD_VK_FUNC
|
||||
|
||||
vr = pvkEnumeratePhysicalDevices( vk_instance, &device_count, NULL );
|
||||
vr = p_vkEnumeratePhysicalDevices( vk_instance, &device_count, NULL );
|
||||
if (vr != VK_SUCCESS || !device_count)
|
||||
{
|
||||
WARN("No Vulkan device found, vr %d, device_count %d.\n", vr, device_count);
|
||||
|
@ -736,7 +740,7 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
|
|||
if (!(vk_physical_devices = calloc( device_count, sizeof(*vk_physical_devices) )))
|
||||
goto done;
|
||||
|
||||
vr = pvkEnumeratePhysicalDevices( vk_instance, &device_count, vk_physical_devices );
|
||||
vr = p_vkEnumeratePhysicalDevices( vk_instance, &device_count, vk_physical_devices );
|
||||
if (vr != VK_SUCCESS)
|
||||
{
|
||||
WARN("vkEnumeratePhysicalDevices failed, vr %d.\n", vr);
|
||||
|
@ -749,8 +753,8 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
|
|||
{
|
||||
for (output_idx = 0; output_idx < provider_info->noutputs; ++output_idx)
|
||||
{
|
||||
vr = pvkGetRandROutputDisplayEXT( vk_physical_devices[device_idx], gdi_display,
|
||||
provider_info->outputs[output_idx], &vk_display );
|
||||
vr = p_vkGetRandROutputDisplayEXT( vk_physical_devices[device_idx], gdi_display,
|
||||
provider_info->outputs[output_idx], &vk_display );
|
||||
if (vr != VK_SUCCESS || vk_display == VK_NULL_HANDLE)
|
||||
continue;
|
||||
|
||||
|
@ -759,7 +763,7 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
|
|||
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
properties2.pNext = &id;
|
||||
|
||||
pvkGetPhysicalDeviceProperties2KHR( vk_physical_devices[device_idx], &properties2 );
|
||||
p_vkGetPhysicalDeviceProperties2KHR( vk_physical_devices[device_idx], &properties2 );
|
||||
for (i = 0; i < prev_gpu_count; ++i)
|
||||
{
|
||||
if (!memcmp( &prev_gpus[i].vulkan_uuid, &id.deviceUUID, sizeof(id.deviceUUID) ))
|
||||
|
@ -788,7 +792,6 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
|
|||
|
||||
done:
|
||||
free( vk_physical_devices );
|
||||
if (vk_instance && pvkDestroyInstance) pvkDestroyInstance( vk_instance, NULL );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ typedef unsigned __int64 mem_size_t;
|
|||
typedef unsigned __int64 file_pos_t;
|
||||
typedef unsigned __int64 client_ptr_t;
|
||||
typedef unsigned __int64 affinity_t;
|
||||
typedef unsigned __int64 object_id_t;
|
||||
typedef client_ptr_t mod_handle_t;
|
||||
|
||||
struct request_header
|
||||
|
@ -882,6 +883,39 @@ struct directory_entry
|
|||
|
||||
|
||||
|
||||
struct shared_cursor
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
unsigned int last_change;
|
||||
};
|
||||
|
||||
typedef volatile struct
|
||||
{
|
||||
struct shared_cursor cursor;
|
||||
} desktop_shm_t;
|
||||
|
||||
typedef volatile union
|
||||
{
|
||||
desktop_shm_t desktop;
|
||||
} object_shm_t;
|
||||
|
||||
typedef volatile struct
|
||||
{
|
||||
LONG64 seq;
|
||||
object_id_t id;
|
||||
object_shm_t shm;
|
||||
} shared_object_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
object_id_t id;
|
||||
mem_size_t offset;
|
||||
} obj_locator_t;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct new_process_request
|
||||
{
|
||||
|
@ -3874,8 +3908,9 @@ struct get_thread_desktop_request
|
|||
struct get_thread_desktop_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
obj_handle_t handle;
|
||||
char __pad_12[4];
|
||||
obj_locator_t locator;
|
||||
obj_handle_t handle;
|
||||
char __pad_28[4];
|
||||
};
|
||||
|
||||
|
||||
|
@ -3888,6 +3923,7 @@ struct set_thread_desktop_request
|
|||
struct set_thread_desktop_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
obj_locator_t locator;
|
||||
};
|
||||
|
||||
|
||||
|
@ -6531,7 +6567,7 @@ union generic_reply
|
|||
|
||||
/* ### protocol_version begin ### */
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 808
|
||||
#define SERVER_PROTOCOL_VERSION 813
|
||||
|
||||
/* ### protocol_version end ### */
|
||||
|
||||
|
|
|
@ -7082,11 +7082,14 @@ static FORCEINLINE void MemoryBarrier(void)
|
|||
*/
|
||||
#if _MSC_VER >= 1700
|
||||
#pragma intrinsic(__iso_volatile_load32)
|
||||
#pragma intrinsic(__iso_volatile_load64)
|
||||
#pragma intrinsic(__iso_volatile_store32)
|
||||
#define __WINE_LOAD32_NO_FENCE(src) (__iso_volatile_load32(src))
|
||||
#define __WINE_LOAD64_NO_FENCE(src) (__iso_volatile_load64(src))
|
||||
#define __WINE_STORE32_NO_FENCE(dest, value) (__iso_volatile_store32(dest, value))
|
||||
#else /* _MSC_VER >= 1700 */
|
||||
#define __WINE_LOAD32_NO_FENCE(src) (*(src))
|
||||
#define __WINE_LOAD64_NO_FENCE(src) (*(src))
|
||||
#define __WINE_STORE32_NO_FENCE(dest, value) ((void)(*(dest) = (value)))
|
||||
#endif /* _MSC_VER >= 1700 */
|
||||
|
||||
|
@ -7120,6 +7123,12 @@ static FORCEINLINE LONG ReadNoFence( LONG const volatile *src )
|
|||
return value;
|
||||
}
|
||||
|
||||
static FORCEINLINE LONG64 ReadNoFence64( LONG64 const volatile *src )
|
||||
{
|
||||
LONG64 value = __WINE_LOAD64_NO_FENCE( (__int64 const volatile *)src );
|
||||
return value;
|
||||
}
|
||||
|
||||
static FORCEINLINE void WriteRelease( LONG volatile *dest, LONG value )
|
||||
{
|
||||
__wine_memory_barrier_acq_rel();
|
||||
|
@ -7306,6 +7315,13 @@ static FORCEINLINE LONG ReadNoFence( LONG const volatile *src )
|
|||
return value;
|
||||
}
|
||||
|
||||
static FORCEINLINE LONG64 ReadNoFence64( LONG64 const volatile *src )
|
||||
{
|
||||
LONG64 value;
|
||||
__WINE_ATOMIC_LOAD_RELAXED( src, &value );
|
||||
return value;
|
||||
}
|
||||
|
||||
static FORCEINLINE void WriteRelease( LONG volatile *dest, LONG value )
|
||||
{
|
||||
__WINE_ATOMIC_STORE_RELEASE( dest, &value );
|
||||
|
|
|
@ -52,6 +52,12 @@ coclass CResamplerMediaObject {}
|
|||
]
|
||||
coclass CMSH264DecoderMFT {}
|
||||
|
||||
[
|
||||
threading(both),
|
||||
uuid(6ca50344-051a-4ded-9779-a43305165e35)
|
||||
]
|
||||
coclass CMSH264EncoderMFT {}
|
||||
|
||||
[
|
||||
uuid(2d709e52-123f-49b5-9cbc-9af5cde28fb9)
|
||||
]
|
||||
|
|
|
@ -153,7 +153,7 @@ static struct
|
|||
{' ',' '}
|
||||
};
|
||||
|
||||
static DIRECTORY_STACK *WCMD_dir_stack_create(const WCHAR *dir, const WCHAR *file)
|
||||
DIRECTORY_STACK *WCMD_dir_stack_create(const WCHAR *dir, const WCHAR *file)
|
||||
{
|
||||
DIRECTORY_STACK *new = xalloc(sizeof(DIRECTORY_STACK));
|
||||
|
||||
|
@ -177,7 +177,7 @@ static DIRECTORY_STACK *WCMD_dir_stack_create(const WCHAR *dir, const WCHAR *fil
|
|||
return new;
|
||||
}
|
||||
|
||||
static DIRECTORY_STACK *WCMD_dir_stack_free(DIRECTORY_STACK *dir)
|
||||
DIRECTORY_STACK *WCMD_dir_stack_free(DIRECTORY_STACK *dir)
|
||||
{
|
||||
DIRECTORY_STACK *next;
|
||||
|
||||
|
@ -228,7 +228,7 @@ static BOOL WCMD_ask_confirm (const WCHAR *message, BOOL showSureText,
|
|||
if (showSureText)
|
||||
WCMD_output_asis (confirm);
|
||||
WCMD_output_asis (options);
|
||||
if (!WCMD_ReadFile(GetStdHandle(STD_INPUT_HANDLE), answer, ARRAY_SIZE(answer), &count))
|
||||
if (!WCMD_ReadFile(GetStdHandle(STD_INPUT_HANDLE), answer, ARRAY_SIZE(answer), &count) || !count)
|
||||
return FALSE;
|
||||
answer[0] = towupper(answer[0]);
|
||||
if (answer[0] == Ybuffer[0])
|
||||
|
@ -1673,110 +1673,6 @@ void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
|
|||
}
|
||||
}
|
||||
|
||||
static BOOL option_equals(WCHAR **haystack, const WCHAR *needle)
|
||||
{
|
||||
int len = wcslen(needle);
|
||||
|
||||
if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
|
||||
*haystack, len, needle, len) == CSTR_EQUAL) {
|
||||
*haystack += len;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* WCMD_parse_forf_options
|
||||
*
|
||||
* Parses the for /f 'options', extracting the values and validating the
|
||||
* keywords. Note all keywords are optional.
|
||||
* Parameters:
|
||||
* options [I] The unparsed parameter string
|
||||
* eol [O] Set to the comment character (eol=x)
|
||||
* skip [O] Set to the number of lines to skip (skip=xx)
|
||||
* delims [O] Set to the token delimiters (delims=)
|
||||
* tokens [O] Set to the requested tokens, as provided (tokens=)
|
||||
* usebackq [O] Set to TRUE if usebackq found
|
||||
*
|
||||
* Returns TRUE on success, FALSE on syntax error
|
||||
*
|
||||
*/
|
||||
static BOOL WCMD_parse_forf_options(WCHAR *options, WCHAR *eol, int *skip,
|
||||
WCHAR *delims, WCHAR *tokens, BOOL *usebackq)
|
||||
{
|
||||
|
||||
WCHAR *pos = options;
|
||||
int len = lstrlenW(pos);
|
||||
|
||||
/* Initialize to defaults */
|
||||
lstrcpyW(delims, L" \t");
|
||||
lstrcpyW(tokens, L"1");
|
||||
*eol = 0;
|
||||
*skip = 0;
|
||||
*usebackq = FALSE;
|
||||
|
||||
/* Strip (optional) leading and trailing quotes */
|
||||
if ((*pos == '"') && (pos[len-1] == '"')) {
|
||||
pos[len-1] = 0;
|
||||
pos++;
|
||||
}
|
||||
|
||||
/* Process each keyword */
|
||||
while (pos && *pos) {
|
||||
if (*pos == ' ' || *pos == '\t') {
|
||||
pos++;
|
||||
|
||||
/* Save End of line character (Ignore line if first token (based on delims) starts with it) */
|
||||
} else if (option_equals(&pos, L"eol=")) {
|
||||
*eol = *pos++;
|
||||
WINE_TRACE("Found eol as %c(%x)\n", *eol, *eol);
|
||||
|
||||
/* Save number of lines to skip (Can be in base 10, hex (0x...) or octal (0xx) */
|
||||
} else if (option_equals(&pos, L"skip=")) {
|
||||
WCHAR *nextchar = NULL;
|
||||
*skip = wcstoul(pos, &nextchar, 0);
|
||||
WINE_TRACE("Found skip as %d lines\n", *skip);
|
||||
pos = nextchar;
|
||||
|
||||
/* Save if usebackq semantics are in effect */
|
||||
} else if (option_equals(&pos, L"usebackq")) {
|
||||
*usebackq = TRUE;
|
||||
WINE_TRACE("Found usebackq\n");
|
||||
|
||||
/* Save the supplied delims. Slightly odd as space can be a delimiter but only
|
||||
if you finish the optionsroot string with delims= otherwise the space is
|
||||
just a token delimiter! */
|
||||
} else if (option_equals(&pos, L"delims=")) {
|
||||
int i=0;
|
||||
|
||||
while (*pos && *pos != ' ') {
|
||||
delims[i++] = *pos;
|
||||
pos++;
|
||||
}
|
||||
if (*pos==' ' && *(pos+1)==0) delims[i++] = *pos;
|
||||
delims[i++] = 0; /* Null terminate the delims */
|
||||
WINE_TRACE("Found delims as '%s'\n", wine_dbgstr_w(delims));
|
||||
|
||||
/* Save the tokens being requested */
|
||||
} else if (option_equals(&pos, L"tokens=")) {
|
||||
int i=0;
|
||||
|
||||
while (*pos && *pos != ' ') {
|
||||
tokens[i++] = *pos;
|
||||
pos++;
|
||||
}
|
||||
tokens[i++] = 0; /* Null terminate the tokens */
|
||||
WINE_TRACE("Found tokens as '%s'\n", wine_dbgstr_w(tokens));
|
||||
|
||||
} else {
|
||||
WINE_WARN("Unexpected data in optionsroot: '%s'\n", wine_dbgstr_w(pos));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* WCMD_add_dirstowalk
|
||||
*
|
||||
|
@ -1790,7 +1686,7 @@ static BOOL WCMD_parse_forf_options(WCHAR *options, WCHAR *eol, int *skip,
|
|||
* processed, and any other directory still to be processed, mimicking what
|
||||
* Windows does
|
||||
*/
|
||||
static void WCMD_add_dirstowalk(DIRECTORY_STACK *dirsToWalk)
|
||||
void WCMD_add_dirstowalk(DIRECTORY_STACK *dirsToWalk)
|
||||
{
|
||||
DIRECTORY_STACK *remainingDirs = dirsToWalk;
|
||||
WCHAR fullitem[MAX_PATH];
|
||||
|
@ -1953,177 +1849,6 @@ int WCMD_for_nexttoken(int lasttoken, const WCHAR *tokenstr,
|
|||
return nexttoken;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* WCMD_parse_line
|
||||
*
|
||||
* When parsing file or string contents (for /f), once the string to parse
|
||||
* has been identified, handle the various options and call the do part
|
||||
* if appropriate.
|
||||
*
|
||||
* Parameters:
|
||||
* cmdStart [I] - Identifies the list of commands making up the
|
||||
* for loop body (especially if brackets in use)
|
||||
* firstCmd [I] - The textual start of the command after the DO
|
||||
* which is within the first item of cmdStart
|
||||
* cmdEnd [O] - Identifies where to continue after the DO
|
||||
* variable [I] - The variable identified on the for line
|
||||
* buffer [I] - The string to parse
|
||||
* doExecuted [O] - Set to TRUE if the DO is ever executed once
|
||||
* forf_skip [I/O] - How many lines to skip first
|
||||
* forf_eol [I] - The 'end of line' (comment) character
|
||||
* forf_delims [I] - The delimiters to use when breaking the string apart
|
||||
* forf_tokens [I] - The tokens to use when breaking the string apart
|
||||
*/
|
||||
static void WCMD_parse_line(CMD_NODE *cmdStart,
|
||||
const WCHAR *firstCmd,
|
||||
CMD_NODE **cmdEnd,
|
||||
int varidx,
|
||||
WCHAR *buffer,
|
||||
BOOL *doExecuted,
|
||||
int *forf_skip,
|
||||
WCHAR forf_eol,
|
||||
WCHAR *forf_delims,
|
||||
WCHAR *forf_tokens) {
|
||||
|
||||
WCHAR *parm;
|
||||
int varoffset;
|
||||
int nexttoken, lasttoken = -1;
|
||||
BOOL starfound = FALSE;
|
||||
BOOL thisduplicate = FALSE;
|
||||
BOOL anyduplicates = FALSE;
|
||||
int totalfound;
|
||||
static WCHAR emptyW[] = L"";
|
||||
|
||||
/* Skip lines if requested */
|
||||
if (*forf_skip) {
|
||||
(*forf_skip)--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save away any existing for variable context (e.g. nested for loops) */
|
||||
WCMD_save_for_loop_context(FALSE);
|
||||
|
||||
/* Extract the parameters based on the tokens= value (There will always
|
||||
be some value, as if it is not supplied, it defaults to tokens=1).
|
||||
Rough logic:
|
||||
Count how many tokens are named in the line, identify the lowest
|
||||
Empty (set to null terminated string) that number of named variables
|
||||
While lasttoken != nextlowest
|
||||
%letter = parameter number 'nextlowest'
|
||||
letter++ (if >26 or >52 abort)
|
||||
Go through token= string finding next lowest number
|
||||
If token ends in * set %letter = raw position of token(nextnumber+1)
|
||||
*/
|
||||
lasttoken = -1;
|
||||
nexttoken = WCMD_for_nexttoken(lasttoken, forf_tokens, &totalfound,
|
||||
&starfound, &thisduplicate);
|
||||
|
||||
/* Empty out variables */
|
||||
for (varoffset=0;
|
||||
varidx >= 0 && varoffset<totalfound && for_var_index_in_range(varidx, varoffset);
|
||||
varoffset++) {
|
||||
WCMD_set_for_loop_variable(varidx + varoffset, emptyW);
|
||||
}
|
||||
|
||||
/* Loop extracting the tokens
|
||||
Note: nexttoken of 0 means there were no tokens requested, to handle
|
||||
the special case of tokens=* */
|
||||
varoffset = 0;
|
||||
WINE_TRACE("Parsing buffer into tokens: '%s'\n", wine_dbgstr_w(buffer));
|
||||
while (varidx >= 0 && (nexttoken > 0 && (nexttoken > lasttoken))) {
|
||||
anyduplicates |= thisduplicate;
|
||||
|
||||
if (!for_var_index_in_range(varidx, varoffset)) break;
|
||||
|
||||
/* Extract the token number requested and set into the next variable context */
|
||||
parm = WCMD_parameter_with_delims(buffer, (nexttoken-1), NULL, TRUE, FALSE, forf_delims);
|
||||
WINE_TRACE("Parsed token %d(%d) as parameter %s\n", nexttoken,
|
||||
varidx + varoffset, wine_dbgstr_w(parm));
|
||||
if (varidx >=0) {
|
||||
if (parm)
|
||||
WCMD_set_for_loop_variable(varidx + varoffset, parm);
|
||||
varoffset++;
|
||||
}
|
||||
|
||||
/* Find the next token */
|
||||
lasttoken = nexttoken;
|
||||
nexttoken = WCMD_for_nexttoken(lasttoken, forf_tokens, NULL,
|
||||
&starfound, &thisduplicate);
|
||||
}
|
||||
|
||||
/* If all the rest of the tokens were requested, and there is still space in
|
||||
the variable range, write them now */
|
||||
if (!anyduplicates && starfound && varidx >= 0 && for_var_index_in_range(varidx, varoffset)) {
|
||||
nexttoken++;
|
||||
WCMD_parameter_with_delims(buffer, (nexttoken-1), &parm, FALSE, FALSE, forf_delims);
|
||||
WINE_TRACE("Parsed allremaining tokens (%d) as parameter %s\n",
|
||||
varidx + varoffset, wine_dbgstr_w(parm));
|
||||
if (parm)
|
||||
WCMD_set_for_loop_variable(varidx + varoffset, parm);
|
||||
}
|
||||
|
||||
/* Execute the body of the foor loop with these values */
|
||||
if (varidx >= 0 && forloopcontext->variable[varidx] && forloopcontext->variable[varidx][0] != forf_eol) {
|
||||
CMD_NODE *thisCmdStart = cmdStart;
|
||||
*doExecuted = TRUE;
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, FALSE, TRUE);
|
||||
*cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
||||
WCMD_restore_for_loop_context();
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* WCMD_forf_getinput
|
||||
*
|
||||
* Return a FILE* which can be used for reading the input lines,
|
||||
* either to a specific file (which may be quote delimited as we have to
|
||||
* read the parameters in raw mode) or to a command which we need to
|
||||
* execute. The command being executed runs in its own shell and stores
|
||||
* its data in a temporary file.
|
||||
*
|
||||
* Parameters:
|
||||
* usebackq [I] - Indicates whether usebackq is in effect or not
|
||||
* itemStr [I] - The item to be handled, either a filename or
|
||||
* whole command string to execute
|
||||
* iscmd [I] - Identifies whether this is a command or not
|
||||
*
|
||||
* Returns a file handle which can be used to read the input lines from.
|
||||
*/
|
||||
static FILE *WCMD_forf_getinput(BOOL usebackq, WCHAR *itemstr, BOOL iscmd)
|
||||
{
|
||||
WCHAR *trimmed = NULL;
|
||||
FILE* ret;
|
||||
|
||||
/* Remove leading and trailing character (but there may be trailing whitespace too) */
|
||||
if ((iscmd && (itemstr[0] == '`' && usebackq)) ||
|
||||
(iscmd && (itemstr[0] == '\'' && !usebackq)) ||
|
||||
(!iscmd && (itemstr[0] == '"' && usebackq)))
|
||||
{
|
||||
trimmed = WCMD_strtrim(itemstr);
|
||||
if (trimmed)
|
||||
itemstr = trimmed;
|
||||
itemstr[lstrlenW(itemstr)-1] = 0x00;
|
||||
itemstr++;
|
||||
}
|
||||
|
||||
if (iscmd)
|
||||
{
|
||||
WCHAR temp_cmd[MAXSTRING];
|
||||
wsprintfW(temp_cmd, L"CMD.EXE /C %s", itemstr);
|
||||
WINE_TRACE("Reading output of '%s'\n", wine_dbgstr_w(temp_cmd));
|
||||
ret = _wpopen(temp_cmd, L"rt,ccs=unicode");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Open the file, read line by line and process */
|
||||
WINE_TRACE("Reading input to parse from '%s'\n", wine_dbgstr_w(itemstr));
|
||||
ret = _wfopen(itemstr, L"rt,ccs=unicode");
|
||||
}
|
||||
free(trimmed);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* WCMD_for
|
||||
*
|
||||
|
@ -2136,411 +1861,6 @@ static FILE *WCMD_forf_getinput(BOOL usebackq, WCHAR *itemstr, BOOL iscmd)
|
|||
*
|
||||
*/
|
||||
|
||||
static void WCMD_for_OLD (WCHAR *p, CMD_NODE **cmdList) {
|
||||
|
||||
WIN32_FIND_DATAW fd;
|
||||
HANDLE hff;
|
||||
int i;
|
||||
const int in_len = lstrlenW(L"in");
|
||||
CMD_NODE *setStart, *thisSet, *cmdStart, *cmdEnd;
|
||||
WCHAR variable[4];
|
||||
int varidx = -1;
|
||||
WCHAR *firstCmd;
|
||||
int thisDepth;
|
||||
WCHAR optionsRoot[MAX_PATH];
|
||||
DIRECTORY_STACK *dirsToWalk = NULL;
|
||||
BOOL expandDirs = FALSE;
|
||||
BOOL useNumbers = FALSE;
|
||||
BOOL doFileset = FALSE;
|
||||
BOOL doRecurse = FALSE;
|
||||
BOOL doExecuted = FALSE; /* Has the 'do' part been executed */
|
||||
LONG numbers[3] = {0,0,0}; /* Defaults to 0 in native */
|
||||
int itemNum;
|
||||
CMD_NODE *thisCmdStart;
|
||||
int parameterNo = 0;
|
||||
WCHAR forf_eol = 0;
|
||||
int forf_skip = 0;
|
||||
WCHAR forf_delims[256];
|
||||
WCHAR forf_tokens[MAXSTRING];
|
||||
BOOL forf_usebackq = FALSE;
|
||||
|
||||
/* Handle optional qualifiers (multiple are allowed) */
|
||||
WCHAR *thisArg = WCMD_parameter(p, parameterNo++, NULL, FALSE, FALSE);
|
||||
|
||||
optionsRoot[0] = 0;
|
||||
while (thisArg && *thisArg == '/') {
|
||||
WINE_TRACE("Processing qualifier at %s\n", wine_dbgstr_w(thisArg));
|
||||
thisArg++;
|
||||
switch (towupper(*thisArg)) {
|
||||
case 'D': expandDirs = TRUE; break;
|
||||
case 'L': useNumbers = TRUE; break;
|
||||
|
||||
/* Recursive is special case - /R can have an optional path following it */
|
||||
/* filenamesets are another special case - /F can have an optional options following it */
|
||||
case 'R':
|
||||
case 'F':
|
||||
{
|
||||
/* When recursing directories, use current directory as the starting point unless
|
||||
subsequently overridden */
|
||||
doRecurse = (towupper(*thisArg) == 'R');
|
||||
if (doRecurse) GetCurrentDirectoryW(ARRAY_SIZE(optionsRoot), optionsRoot);
|
||||
|
||||
doFileset = (towupper(*thisArg) == 'F');
|
||||
|
||||
/* Retrieve next parameter to see if is root/options (raw form required
|
||||
with for /f, or unquoted in for /r) */
|
||||
thisArg = WCMD_parameter(p, parameterNo, NULL, doFileset, FALSE);
|
||||
|
||||
/* Next parm is either qualifier, path/options or variable -
|
||||
only care about it if it is the path/options */
|
||||
if (thisArg && *thisArg != '/' && *thisArg != '%') {
|
||||
parameterNo++;
|
||||
lstrcpyW(optionsRoot, thisArg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WINE_FIXME("for qualifier '%c' unhandled\n", *thisArg);
|
||||
}
|
||||
|
||||
/* Step to next token */
|
||||
thisArg = WCMD_parameter(p, parameterNo++, NULL, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/* Ensure line continues with variable */
|
||||
if (*thisArg != '%') {
|
||||
WCMD_output_stderr (WCMD_LoadMessage(WCMD_SYNTAXERR));
|
||||
return;
|
||||
}
|
||||
|
||||
/* With for /f parse the options if provided */
|
||||
if (doFileset) {
|
||||
if (!WCMD_parse_forf_options(optionsRoot, &forf_eol, &forf_skip,
|
||||
forf_delims, forf_tokens, &forf_usebackq))
|
||||
{
|
||||
WCMD_output_stderr (WCMD_LoadMessage(WCMD_SYNTAXERR));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set up the list of directories to recurse if we are going to */
|
||||
} else if (doRecurse) {
|
||||
/* Allocate memory, add to list */
|
||||
dirsToWalk = WCMD_dir_stack_create(optionsRoot, NULL);
|
||||
TRACE("Starting with root directory %s\n", wine_dbgstr_w(dirsToWalk->dirName));
|
||||
}
|
||||
|
||||
/* Variable should follow */
|
||||
lstrcpyW(variable, thisArg);
|
||||
WINE_TRACE("Variable identified as %s\n", wine_dbgstr_w(variable));
|
||||
varidx = for_var_char_to_index(variable[1]);
|
||||
|
||||
/* Ensure line continues with IN */
|
||||
thisArg = WCMD_parameter(p, parameterNo++, NULL, FALSE, FALSE);
|
||||
if (!thisArg
|
||||
|| !(CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
|
||||
thisArg, in_len, L"in", in_len) == CSTR_EQUAL)) {
|
||||
WCMD_output_stderr (WCMD_LoadMessage(WCMD_SYNTAXERR));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save away where the set of data starts and the variable */
|
||||
thisDepth = CMD_node_get_depth(*cmdList);
|
||||
*cmdList = CMD_node_next(*cmdList);
|
||||
setStart = (*cmdList);
|
||||
|
||||
/* Skip until the close bracket */
|
||||
WINE_TRACE("Searching %p as the set\n", *cmdList);
|
||||
while (*cmdList &&
|
||||
CMD_node_get_command(*cmdList)->command != NULL &&
|
||||
CMD_node_get_depth(*cmdList) > thisDepth) {
|
||||
WINE_TRACE("Skipping %p which is part of the set\n", *cmdList);
|
||||
*cmdList = CMD_node_next(*cmdList);
|
||||
}
|
||||
|
||||
/* Skip the close bracket, if there is one */
|
||||
if (*cmdList) *cmdList = CMD_node_next(*cmdList);
|
||||
|
||||
/* Syntax error if missing close bracket, or nothing following it
|
||||
and once we have the complete set, we expect a DO */
|
||||
WINE_TRACE("Looking for 'do ' in %p\n", *cmdList);
|
||||
if ((*cmdList == NULL) || !WCMD_keyword_ws_found(L"do", CMD_node_get_command(*cmdList)->command)) {
|
||||
WCMD_output_stderr (WCMD_LoadMessage(WCMD_SYNTAXERR));
|
||||
return;
|
||||
}
|
||||
|
||||
cmdEnd = *cmdList;
|
||||
|
||||
/* Loop repeatedly per-directory we are potentially walking, when in for /r
|
||||
mode, or once for the rest of the time. */
|
||||
do {
|
||||
|
||||
/* Save away the starting position for the commands (and offset for the
|
||||
first one) */
|
||||
cmdStart = *cmdList;
|
||||
firstCmd = CMD_node_get_command(*cmdList)->command + 3; /* Skip 'do ' */
|
||||
itemNum = 0;
|
||||
|
||||
/* If we are recursing directories (ie /R), add all sub directories now, then
|
||||
prefix the root when searching for the item */
|
||||
if (dirsToWalk) WCMD_add_dirstowalk(dirsToWalk);
|
||||
|
||||
thisSet = setStart;
|
||||
/* Loop through all set entries */
|
||||
while (thisSet &&
|
||||
CMD_node_get_command(thisSet)->command != NULL &&
|
||||
CMD_node_get_depth(thisSet) >= thisDepth) {
|
||||
|
||||
/* Loop through all entries on the same line */
|
||||
WCHAR *staticitem;
|
||||
WCHAR *itemStart;
|
||||
WCHAR buffer[MAXSTRING];
|
||||
|
||||
WINE_TRACE("Processing for set %p\n", thisSet);
|
||||
i = 0;
|
||||
while (*(staticitem = WCMD_parameter (CMD_node_get_command(thisSet)->command, i, &itemStart, TRUE, FALSE))) {
|
||||
|
||||
/*
|
||||
* If the parameter within the set has a wildcard then search for matching files
|
||||
* otherwise do a literal substitution.
|
||||
*/
|
||||
|
||||
/* Take a copy of the item returned from WCMD_parameter as it is held in a
|
||||
static buffer which can be overwritten during parsing of the for body */
|
||||
WCHAR item[MAXSTRING];
|
||||
lstrcpyW(item, staticitem);
|
||||
|
||||
thisCmdStart = cmdStart;
|
||||
|
||||
itemNum++;
|
||||
WINE_TRACE("Processing for item %d '%s'\n", itemNum, wine_dbgstr_w(item));
|
||||
|
||||
if (!useNumbers && !doFileset) {
|
||||
WCHAR fullitem[MAX_PATH];
|
||||
int prefixlen = 0;
|
||||
|
||||
/* Now build the item to use / search for in the specified directory,
|
||||
as it is fully qualified in the /R case */
|
||||
if (dirsToWalk) {
|
||||
lstrcpyW(fullitem, dirsToWalk->dirName);
|
||||
lstrcatW(fullitem, L"\\");
|
||||
lstrcatW(fullitem, item);
|
||||
} else {
|
||||
WCHAR *prefix = wcsrchr(item, '\\');
|
||||
if (prefix) prefixlen = (prefix - item) + 1;
|
||||
lstrcpyW(fullitem, item);
|
||||
}
|
||||
|
||||
if (wcspbrk(fullitem, L"*?")) {
|
||||
hff = FindFirstFileW(fullitem, &fd);
|
||||
if (hff != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
BOOL isDirectory = FALSE;
|
||||
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) isDirectory = TRUE;
|
||||
|
||||
/* Handle as files or dirs appropriately, but ignore . and .. */
|
||||
if (isDirectory == expandDirs &&
|
||||
(lstrcmpW(fd.cFileName, L"..") != 0) && (lstrcmpW(fd.cFileName, L".") != 0))
|
||||
{
|
||||
thisCmdStart = cmdStart;
|
||||
WINE_TRACE("Processing FOR filename %s\n", wine_dbgstr_w(fd.cFileName));
|
||||
|
||||
if (doRecurse) {
|
||||
if (wcslen(dirsToWalk->dirName) + 1 + wcslen(fd.cFileName) >= MAX_PATH)
|
||||
{
|
||||
WINE_TRACE("Skipping too long path %s\\%s\n",
|
||||
debugstr_w(dirsToWalk->dirName), debugstr_w(fd.cFileName));
|
||||
continue;
|
||||
}
|
||||
lstrcpyW(fullitem, dirsToWalk->dirName);
|
||||
lstrcatW(fullitem, L"\\");
|
||||
lstrcatW(fullitem, fd.cFileName);
|
||||
} else {
|
||||
if (prefixlen) lstrcpynW(fullitem, item, prefixlen + 1);
|
||||
fullitem[prefixlen] = 0x00;
|
||||
lstrcatW(fullitem, fd.cFileName);
|
||||
}
|
||||
doExecuted = TRUE;
|
||||
|
||||
WCMD_save_for_loop_context(FALSE);
|
||||
/* Save away any existing for variable context (e.g. nested for loops)
|
||||
and restore it after executing the body of this for loop */
|
||||
if (varidx >= 0)
|
||||
WCMD_set_for_loop_variable(varidx, fullitem);
|
||||
WCMD_part_execute (&thisCmdStart, firstCmd, FALSE, TRUE);
|
||||
WCMD_restore_for_loop_context();
|
||||
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
} while (FindNextFileW(hff, &fd) != 0);
|
||||
FindClose (hff);
|
||||
}
|
||||
} else {
|
||||
doExecuted = TRUE;
|
||||
|
||||
WCMD_save_for_loop_context(FALSE);
|
||||
/* Save away any existing for variable context (e.g. nested for loops)
|
||||
and restore it after executing the body of this for loop */
|
||||
if (varidx >= 0)
|
||||
WCMD_set_for_loop_variable(varidx, fullitem);
|
||||
WCMD_part_execute (&thisCmdStart, firstCmd, FALSE, TRUE);
|
||||
WCMD_restore_for_loop_context();
|
||||
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
||||
} else if (useNumbers) {
|
||||
/* Convert the first 3 numbers to signed longs and save */
|
||||
if (itemNum <=3) numbers[itemNum-1] = wcstol(item, NULL, 10);
|
||||
/* else ignore them! */
|
||||
|
||||
/* Filesets - either a list of files, or a command to run and parse the output */
|
||||
} else if (doFileset && ((!forf_usebackq && *itemStart != '"') ||
|
||||
(forf_usebackq && *itemStart != '\''))) {
|
||||
|
||||
FILE *input;
|
||||
WCHAR *itemparm;
|
||||
|
||||
WINE_TRACE("Processing for filespec from item %d '%s'\n", itemNum,
|
||||
wine_dbgstr_w(item));
|
||||
|
||||
/* If backquote or single quote, we need to launch that command
|
||||
and parse the results - use a temporary file */
|
||||
if ((forf_usebackq && *itemStart == '`') ||
|
||||
(!forf_usebackq && *itemStart == '\'')) {
|
||||
|
||||
/* Use itemstart because the command is the whole set, not just the first token */
|
||||
itemparm = itemStart;
|
||||
} else {
|
||||
|
||||
/* Use item because the file to process is just the first item in the set */
|
||||
itemparm = item;
|
||||
}
|
||||
input = WCMD_forf_getinput(forf_usebackq, itemparm, (itemparm==itemStart));
|
||||
|
||||
/* Process the input file */
|
||||
if (!input) {
|
||||
WCMD_print_error ();
|
||||
WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), item);
|
||||
errorlevel = 1;
|
||||
return; /* FOR loop aborts at first failure here */
|
||||
|
||||
} else {
|
||||
|
||||
/* Read line by line until end of file */
|
||||
while (fgetws(buffer, ARRAY_SIZE(buffer), input)) {
|
||||
size_t len = wcslen(buffer);
|
||||
/* Either our buffer isn't large enough to fit a full line, or there's a stray
|
||||
* '\0' in the buffer.
|
||||
*/
|
||||
if (!feof(input) && (len == 0 || (buffer[len - 1] != '\n' && buffer[len - 1] != '\r')))
|
||||
break;
|
||||
while (len && (buffer[len - 1] == '\n' || buffer[len - 1] == '\r'))
|
||||
buffer[--len] = L'\0';
|
||||
WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, for_var_char_to_index(variable[1]), buffer, &doExecuted,
|
||||
&forf_skip, forf_eol, forf_delims, forf_tokens);
|
||||
buffer[0] = 0;
|
||||
}
|
||||
fclose (input);
|
||||
}
|
||||
|
||||
/* When we have processed the item as a whole command, abort future set processing */
|
||||
if (itemparm==itemStart) {
|
||||
thisSet = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Filesets - A string literal */
|
||||
} else if (doFileset && ((!forf_usebackq && *itemStart == '"') ||
|
||||
(forf_usebackq && *itemStart == '\''))) {
|
||||
|
||||
/* Remove leading and trailing character, ready to parse with delims= delimiters
|
||||
Note that the last quote is removed from the set and the string terminates
|
||||
there to mimic windows */
|
||||
WCHAR *strend = wcsrchr(itemStart, forf_usebackq?'\'':'"');
|
||||
if (strend) {
|
||||
*strend = 0x00;
|
||||
itemStart++;
|
||||
}
|
||||
|
||||
/* Copy the item away from the global buffer used by WCMD_parameter */
|
||||
lstrcpyW(buffer, itemStart);
|
||||
WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, for_var_char_to_index(variable[1]), buffer, &doExecuted,
|
||||
&forf_skip, forf_eol, forf_delims, forf_tokens);
|
||||
|
||||
/* Only one string can be supplied in the whole set, abort future set processing */
|
||||
thisSet = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
WINE_TRACE("Post-command, cmdEnd = %p\n", cmdEnd);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Move onto the next set line */
|
||||
if (thisSet) thisSet = CMD_node_next(thisSet);
|
||||
}
|
||||
|
||||
/* If /L is provided, now run the for loop */
|
||||
if (useNumbers) {
|
||||
WCHAR thisNum[20];
|
||||
|
||||
WINE_TRACE("FOR /L provided range from %ld to %ld step %ld\n",
|
||||
numbers[0], numbers[2], numbers[1]);
|
||||
for (i=numbers[0];
|
||||
(numbers[1]<0)? i>=numbers[2] : i<=numbers[2];
|
||||
i=i + numbers[1]) {
|
||||
|
||||
swprintf(thisNum, ARRAY_SIZE(thisNum), L"%d", i);
|
||||
WINE_TRACE("Processing FOR number %s\n", wine_dbgstr_w(thisNum));
|
||||
|
||||
thisCmdStart = cmdStart;
|
||||
doExecuted = TRUE;
|
||||
|
||||
/* Save away any existing for variable context (e.g. nested for loops)
|
||||
and restore it after executing the body of this for loop */
|
||||
if (varidx >= 0)
|
||||
{
|
||||
WCMD_save_for_loop_context(FALSE);
|
||||
WCMD_set_for_loop_variable(varidx, thisNum);
|
||||
}
|
||||
WCMD_part_execute (&thisCmdStart, firstCmd, FALSE, TRUE);
|
||||
if (varidx >= 0)
|
||||
WCMD_restore_for_loop_context();
|
||||
}
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
||||
/* If we are walking directories, move on to any which remain */
|
||||
if (dirsToWalk != NULL) {
|
||||
dirsToWalk = WCMD_dir_stack_free(dirsToWalk);
|
||||
if (dirsToWalk) WINE_TRACE("Moving to next directory to iterate: %s\n",
|
||||
wine_dbgstr_w(dirsToWalk->dirName));
|
||||
else WINE_TRACE("Finished all directories.\n");
|
||||
}
|
||||
|
||||
} while (dirsToWalk != NULL);
|
||||
|
||||
/* Now skip over the do part if we did not perform the for loop so far.
|
||||
We store in cmdEnd the next command after the do block, but we only
|
||||
know this if something was run. If it has not been, we need to calculate
|
||||
it. */
|
||||
if (!doExecuted) {
|
||||
thisCmdStart = cmdStart;
|
||||
WINE_TRACE("Skipping for loop commands due to no valid iterations\n");
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, FALSE, FALSE);
|
||||
cmdEnd = thisCmdStart;
|
||||
}
|
||||
|
||||
/* When the loop ends, either something like a GOTO or EXIT /b has terminated
|
||||
all processing, OR it should be pointing to the end of && processing OR
|
||||
it should be pointing at the NULL end of bracket for the DO. The return
|
||||
value needs to be the NEXT command to execute, which it either is, or
|
||||
we need to step over the closing bracket */
|
||||
*cmdList = cmdEnd;
|
||||
if (cmdEnd && CMD_node_get_command(cmdEnd)->command == NULL) *cmdList = CMD_node_next(cmdEnd);
|
||||
}
|
||||
|
||||
void WCMD_for(WCHAR *p, CMD_NODE **cmdList)
|
||||
{
|
||||
CMD_FOR_CONTROL *for_ctrl;
|
||||
|
@ -2548,8 +1868,7 @@ void WCMD_for(WCHAR *p, CMD_NODE **cmdList)
|
|||
for_ctrl = for_control_parse(p);
|
||||
if (!for_ctrl)
|
||||
{
|
||||
/* temporary code: use OLD code for non migrated FOR constructs */
|
||||
WCMD_for_OLD(p, cmdList);
|
||||
*cmdList = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -610,8 +610,8 @@ N
|
|||
''
|
||||
'.eh'@or_broken@''
|
||||
"foo bar"
|
||||
@todo_wine@foo
|
||||
@todo_wine@bar
|
||||
foo
|
||||
bar
|
||||
--- in digit variables
|
||||
a %1 %2
|
||||
b %1 %2
|
||||
|
|
|
@ -83,16 +83,20 @@ typedef struct _CMD_IF_CONDITION
|
|||
};
|
||||
} CMD_IF_CONDITION;
|
||||
|
||||
#define CMD_FOR_FLAG_TREE_RECURSE (1u << 0)
|
||||
#define CMD_FOR_FLAG_TREE_INCLUDE_FILES (1u << 1)
|
||||
#define CMD_FOR_FLAG_TREE_INCLUDE_DIRECTORIES (1u << 2)
|
||||
|
||||
typedef struct _CMD_FOR_CONTROL
|
||||
{
|
||||
enum for_control_operator {
|
||||
CMD_FOR_FILE_SET /* /F */,
|
||||
enum for_control_operator {CMD_FOR_FILETREE, CMD_FOR_FILE_SET /* /F */,
|
||||
CMD_FOR_NUMBERS /* /L */} operator;
|
||||
unsigned flags; /* |-ed CMD_FOR_FLAG_* */
|
||||
int variable_index;
|
||||
const WCHAR *set;
|
||||
union
|
||||
{
|
||||
const WCHAR *root_dir; /* for CMD_FOR_FILETREE */
|
||||
struct /* for CMD_FOR_FILE_SET */
|
||||
{
|
||||
WCHAR eol;
|
||||
|
@ -164,6 +168,10 @@ int WCMD_for_nexttoken(int lasttoken, const WCHAR *tokenstr,
|
|||
BOOL *duplicates);
|
||||
void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
|
||||
BOOL isIF, BOOL executecmds);
|
||||
struct _DIRECTORY_STACK;
|
||||
void WCMD_add_dirstowalk(struct _DIRECTORY_STACK *dirsToWalk);
|
||||
struct _DIRECTORY_STACK *WCMD_dir_stack_create(const WCHAR *dir, const WCHAR *file);
|
||||
struct _DIRECTORY_STACK *WCMD_dir_stack_free(struct _DIRECTORY_STACK *dir);
|
||||
|
||||
void WCMD_assoc (const WCHAR *, BOOL);
|
||||
void WCMD_batch (WCHAR *, WCHAR *, BOOL, WCHAR *, HANDLE);
|
||||
|
|
|
@ -1000,6 +1000,9 @@ void for_control_dispose(CMD_FOR_CONTROL *for_ctrl)
|
|||
free((void*)for_ctrl->delims);
|
||||
free((void*)for_ctrl->tokens);
|
||||
break;
|
||||
case CMD_FOR_FILETREE:
|
||||
free((void*)for_ctrl->root_dir);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1007,7 +1010,7 @@ void for_control_dispose(CMD_FOR_CONTROL *for_ctrl)
|
|||
|
||||
const char *debugstr_for_control(const CMD_FOR_CONTROL *for_ctrl)
|
||||
{
|
||||
static const char* for_ctrl_strings[] = {"file", "numbers"};
|
||||
static const char* for_ctrl_strings[] = {"tree", "file", "numbers"};
|
||||
const char *flags, *options;
|
||||
|
||||
if (for_ctrl->operator >= ARRAY_SIZE(for_ctrl_strings))
|
||||
|
@ -1016,9 +1019,18 @@ const char *debugstr_for_control(const CMD_FOR_CONTROL *for_ctrl)
|
|||
return wine_dbg_sprintf("<<%u>>", for_ctrl->operator);
|
||||
}
|
||||
|
||||
flags = "";
|
||||
if (for_ctrl->flags)
|
||||
flags = wine_dbg_sprintf("flags=%s%s%s ",
|
||||
(for_ctrl->flags & CMD_FOR_FLAG_TREE_RECURSE) ? "~recurse" : "",
|
||||
(for_ctrl->flags & CMD_FOR_FLAG_TREE_INCLUDE_FILES) ? "~+files" : "",
|
||||
(for_ctrl->flags & CMD_FOR_FLAG_TREE_INCLUDE_DIRECTORIES) ? "~+dirs" : "");
|
||||
else
|
||||
flags = "";
|
||||
switch (for_ctrl->operator)
|
||||
{
|
||||
case CMD_FOR_FILETREE:
|
||||
options = wine_dbg_sprintf("root=(%ls) ", for_ctrl->root_dir);
|
||||
break;
|
||||
case CMD_FOR_FILE_SET:
|
||||
{
|
||||
WCHAR eol_buf[4] = {L'\'', for_ctrl->eol, L'\'', L'\0'};
|
||||
|
@ -1045,6 +1057,9 @@ void for_control_create(enum for_control_operator for_op, unsigned flags, const
|
|||
for_ctrl->set = NULL;
|
||||
switch (for_ctrl->operator)
|
||||
{
|
||||
case CMD_FOR_FILETREE:
|
||||
for_ctrl->root_dir = options && *options ? xstrdupW(options) : NULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2239,6 +2254,22 @@ CMD_FOR_CONTROL *for_control_parse(WCHAR *opts_var)
|
|||
}
|
||||
switch (mode)
|
||||
{
|
||||
case L' ':
|
||||
for_op = CMD_FOR_FILETREE;
|
||||
flags = CMD_FOR_FLAG_TREE_INCLUDE_FILES;
|
||||
break;
|
||||
case L'D':
|
||||
for_op = CMD_FOR_FILETREE;
|
||||
flags = CMD_FOR_FLAG_TREE_INCLUDE_DIRECTORIES;
|
||||
break;
|
||||
case L'X':
|
||||
for_op = CMD_FOR_FILETREE;
|
||||
flags = CMD_FOR_FLAG_TREE_INCLUDE_DIRECTORIES | CMD_FOR_FLAG_TREE_RECURSE;
|
||||
break;
|
||||
case L'R':
|
||||
for_op = CMD_FOR_FILETREE;
|
||||
flags = CMD_FOR_FLAG_TREE_INCLUDE_FILES | /*CMD_FOR_FLAG_TREE_INCLUDE_DIRECTORIES | */CMD_FOR_FLAG_TREE_RECURSE;
|
||||
break;
|
||||
case L'L':
|
||||
for_op = CMD_FOR_NUMBERS;
|
||||
break;
|
||||
|
@ -2246,10 +2277,11 @@ CMD_FOR_CONTROL *for_control_parse(WCHAR *opts_var)
|
|||
for_op = CMD_FOR_FILE_SET;
|
||||
break;
|
||||
default:
|
||||
FIXME("Unexpected situation\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mode == L'F')
|
||||
if (mode == L'F' || mode == L'R')
|
||||
{
|
||||
/* Retrieve next parameter to see if is root/options (raw form required
|
||||
* with for /f, or unquoted in for /r)
|
||||
|
@ -3205,6 +3237,109 @@ static CMD_NODE *for_control_execute_fileset(CMD_FOR_CONTROL *for_ctrl, CMD_NODE
|
|||
return body;
|
||||
}
|
||||
|
||||
static CMD_NODE *for_control_execute_set(CMD_FOR_CONTROL *for_ctrl, const WCHAR *from_dir, size_t ref_len, CMD_NODE *cmdList)
|
||||
{
|
||||
CMD_NODE *body = NULL;
|
||||
size_t len;
|
||||
WCHAR set[MAXSTRING];
|
||||
WCHAR buffer[MAX_PATH];
|
||||
int i;
|
||||
|
||||
if (from_dir)
|
||||
{
|
||||
len = wcslen(from_dir) + 1;
|
||||
if (len >= ARRAY_SIZE(buffer)) return NULL;
|
||||
wcscpy(buffer, from_dir);
|
||||
wcscat(buffer, L"\\");
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
|
||||
wcscpy(set, for_ctrl->set);
|
||||
handleExpansion(set, context != NULL, delayedsubst);
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
WCHAR *element = WCMD_parameter(set, i, NULL, TRUE, FALSE);
|
||||
if (!element || !*element) break;
|
||||
if (len + wcslen(element) + 1 >= ARRAY_SIZE(buffer)) continue;
|
||||
|
||||
wcscpy(&buffer[len], element);
|
||||
|
||||
TRACE("Doing set element %ls\n", buffer);
|
||||
|
||||
if (wcspbrk(element, L"?*"))
|
||||
{
|
||||
WIN32_FIND_DATAW fd;
|
||||
HANDLE hff = FindFirstFileW(buffer, &fd);
|
||||
size_t insert_pos = (wcsrchr(buffer, L'\\') ? wcsrchr(buffer, L'\\') + 1 - buffer : 0);
|
||||
|
||||
if (hff == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
TRACE("Couldn't FindFirstFile on %ls\n", buffer);
|
||||
continue;
|
||||
}
|
||||
do
|
||||
{
|
||||
TRACE("Considering %ls\n", fd.cFileName);
|
||||
if (!lstrcmpW(fd.cFileName, L"..") || !lstrcmpW(fd.cFileName, L".")) continue;
|
||||
if (!(for_ctrl->flags & CMD_FOR_FLAG_TREE_INCLUDE_FILES) &&
|
||||
!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
continue;
|
||||
if (!(for_ctrl->flags & CMD_FOR_FLAG_TREE_INCLUDE_DIRECTORIES) &&
|
||||
(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
continue;
|
||||
|
||||
if (insert_pos + wcslen(fd.cFileName) + 1 >= ARRAY_SIZE(buffer)) continue;
|
||||
wcscpy(&buffer[insert_pos], fd.cFileName);
|
||||
|
||||
body = cmdList;
|
||||
WCMD_set_for_loop_variable(for_ctrl->variable_index, buffer);
|
||||
WCMD_part_execute(&body, CMD_node_get_command(body)->command + 3, FALSE, TRUE);
|
||||
} while (FindNextFileW(hff, &fd) != 0);
|
||||
FindClose(hff);
|
||||
}
|
||||
else
|
||||
{
|
||||
body = cmdList;
|
||||
WCMD_set_for_loop_variable(for_ctrl->variable_index, buffer);
|
||||
WCMD_part_execute(&body, CMD_node_get_command(body)->command + 3, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
static CMD_NODE *for_control_execute_walk_files(CMD_FOR_CONTROL *for_ctrl, CMD_NODE *cmdList)
|
||||
{
|
||||
DIRECTORY_STACK *dirs_to_walk;
|
||||
size_t ref_len;
|
||||
CMD_NODE *body = NULL;
|
||||
|
||||
if (for_ctrl->root_dir)
|
||||
{
|
||||
WCHAR buffer[MAXSTRING];
|
||||
|
||||
wcscpy(buffer, for_ctrl->root_dir);
|
||||
handleExpansion(buffer, context != NULL, delayedsubst);
|
||||
dirs_to_walk = WCMD_dir_stack_create(buffer, NULL);
|
||||
}
|
||||
else dirs_to_walk = WCMD_dir_stack_create(NULL, NULL);
|
||||
ref_len = wcslen(dirs_to_walk->dirName);
|
||||
|
||||
while (dirs_to_walk)
|
||||
{
|
||||
TRACE("About to walk %p %ls for %s\n", dirs_to_walk, dirs_to_walk->dirName, debugstr_for_control(for_ctrl));
|
||||
if (for_ctrl->flags & CMD_FOR_FLAG_TREE_RECURSE)
|
||||
WCMD_add_dirstowalk(dirs_to_walk);
|
||||
|
||||
body = for_control_execute_set(for_ctrl, dirs_to_walk->dirName, ref_len, cmdList);
|
||||
/* If we are walking directories, move on to any which remain */
|
||||
dirs_to_walk = WCMD_dir_stack_free(dirs_to_walk);
|
||||
}
|
||||
TRACE("Finished all directories.\n");
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
static CMD_NODE *for_control_execute_numbers(CMD_FOR_CONTROL *for_ctrl, CMD_NODE *cmdList)
|
||||
{
|
||||
WCHAR set[MAXSTRING];
|
||||
|
@ -3250,6 +3385,12 @@ void for_control_execute(CMD_FOR_CONTROL *for_ctrl, CMD_NODE **cmdList)
|
|||
|
||||
switch (for_ctrl->operator)
|
||||
{
|
||||
case CMD_FOR_FILETREE:
|
||||
if (for_ctrl->flags & CMD_FOR_FLAG_TREE_RECURSE)
|
||||
last = for_control_execute_walk_files(for_ctrl, *cmdList);
|
||||
else
|
||||
last = for_control_execute_set(for_ctrl, NULL, 0, *cmdList);
|
||||
break;
|
||||
case CMD_FOR_FILE_SET:
|
||||
last = for_control_execute_fileset(for_ctrl, *cmdList);
|
||||
break;
|
||||
|
|
|
@ -439,11 +439,14 @@ void init_directories( struct fd *intl_fd )
|
|||
/* mappings */
|
||||
static const WCHAR intlW[] = {'N','l','s','S','e','c','t','i','o','n','L','A','N','G','_','I','N','T','L'};
|
||||
static const WCHAR user_dataW[] = {'_','_','w','i','n','e','_','u','s','e','r','_','s','h','a','r','e','d','_','d','a','t','a'};
|
||||
static const WCHAR sessionW[] = {'_','_','w','i','n','e','_','s','e','s','s','i','o','n'};
|
||||
static const struct unicode_str intl_str = {intlW, sizeof(intlW)};
|
||||
static const struct unicode_str user_data_str = {user_dataW, sizeof(user_dataW)};
|
||||
static const struct unicode_str session_str = {sessionW, sizeof(sessionW)};
|
||||
|
||||
struct directory *dir_driver, *dir_device, *dir_global, *dir_kernel, *dir_nls;
|
||||
struct object *named_pipe_device, *mailslot_device, *null_device;
|
||||
struct mapping *session_mapping;
|
||||
unsigned int i;
|
||||
|
||||
root_directory = create_directory( NULL, NULL, OBJ_PERMANENT, HASH_SIZE, NULL );
|
||||
|
@ -491,6 +494,10 @@ void init_directories( struct fd *intl_fd )
|
|||
release_object( create_user_data_mapping( &dir_kernel->obj, &user_data_str, OBJ_PERMANENT, NULL ));
|
||||
release_object( intl_fd );
|
||||
|
||||
session_mapping = create_session_mapping( &dir_kernel->obj, &session_str, OBJ_PERMANENT, NULL );
|
||||
set_session_mapping( session_mapping );
|
||||
release_object( session_mapping );
|
||||
|
||||
release_object( named_pipe_device );
|
||||
release_object( mailslot_device );
|
||||
release_object( null_device );
|
||||
|
|
|
@ -188,6 +188,29 @@ extern struct mapping *create_fd_mapping( struct object *root, const struct unic
|
|||
unsigned int attr, const struct security_descriptor *sd );
|
||||
extern struct object *create_user_data_mapping( struct object *root, const struct unicode_str *name,
|
||||
unsigned int attr, const struct security_descriptor *sd );
|
||||
extern struct mapping *create_session_mapping( struct object *root, const struct unicode_str *name,
|
||||
unsigned int attr, const struct security_descriptor *sd );
|
||||
extern void set_session_mapping( struct mapping *mapping );
|
||||
|
||||
extern const volatile void *alloc_shared_object(void);
|
||||
extern void free_shared_object( const volatile void *object_shm );
|
||||
extern obj_locator_t get_shared_object_locator( const volatile void *object_shm );
|
||||
|
||||
#define SHARED_WRITE_BEGIN( object_shm, type ) \
|
||||
do { \
|
||||
const type *__shared = (object_shm); \
|
||||
type *shared = (type *)__shared; \
|
||||
shared_object_t *__obj = CONTAINING_RECORD( shared, shared_object_t, shm ); \
|
||||
LONG64 __seq = __obj->seq + 1, __end = __seq + 1; \
|
||||
assert( (__seq & 1) != 0 ); \
|
||||
__WINE_ATOMIC_STORE_RELEASE( &__obj->seq, &__seq ); \
|
||||
do
|
||||
|
||||
#define SHARED_WRITE_END \
|
||||
while(0); \
|
||||
assert( __seq == __obj->seq ); \
|
||||
__WINE_ATOMIC_STORE_RELEASE( &__obj->seq, &__end ); \
|
||||
} while(0)
|
||||
|
||||
/* device functions */
|
||||
|
||||
|
|
158
server/mapping.c
158
server/mapping.c
|
@ -225,6 +225,36 @@ static const mem_size_t granularity_mask = 0xffff;
|
|||
static struct addr_range ranges32;
|
||||
static struct addr_range ranges64;
|
||||
|
||||
struct session_block
|
||||
{
|
||||
struct list entry; /* entry in the session block list */
|
||||
const char *data; /* base pointer for the mmaped data */
|
||||
mem_size_t offset; /* offset of data in the session shared mapping */
|
||||
mem_size_t used_size; /* used size for previously allocated objects */
|
||||
mem_size_t block_size; /* total size of the block */
|
||||
};
|
||||
|
||||
struct session_object
|
||||
{
|
||||
struct list entry; /* entry in the session free object list */
|
||||
mem_size_t offset; /* offset of obj in the session shared mapping */
|
||||
shared_object_t obj; /* object actually shared with the client */
|
||||
};
|
||||
|
||||
struct session
|
||||
{
|
||||
struct list blocks;
|
||||
struct list free_objects;
|
||||
object_id_t last_object_id;
|
||||
};
|
||||
|
||||
static struct mapping *session_mapping;
|
||||
static struct session session =
|
||||
{
|
||||
.blocks = LIST_INIT(session.blocks),
|
||||
.free_objects = LIST_INIT(session.free_objects),
|
||||
};
|
||||
|
||||
#define ROUND_SIZE(size) (((size) + page_mask) & ~page_mask)
|
||||
|
||||
void init_memory(void)
|
||||
|
@ -1256,6 +1286,134 @@ int get_page_size(void)
|
|||
return page_mask + 1;
|
||||
}
|
||||
|
||||
struct mapping *create_session_mapping( struct object *root, const struct unicode_str *name,
|
||||
unsigned int attr, const struct security_descriptor *sd )
|
||||
{
|
||||
static const unsigned int access = FILE_READ_DATA | FILE_WRITE_DATA;
|
||||
mem_size_t size = max( sizeof(shared_object_t) * 512, 0x10000 );
|
||||
|
||||
return create_mapping( root, name, attr, size, SEC_COMMIT, 0, access, sd );
|
||||
}
|
||||
|
||||
void set_session_mapping( struct mapping *mapping )
|
||||
{
|
||||
int unix_fd = get_unix_fd( mapping->fd );
|
||||
mem_size_t size = mapping->size;
|
||||
struct session_block *block;
|
||||
void *tmp;
|
||||
|
||||
if (!(block = mem_alloc( sizeof(*block) ))) return;
|
||||
if ((tmp = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, unix_fd, 0 )) == MAP_FAILED)
|
||||
{
|
||||
free( block );
|
||||
return;
|
||||
}
|
||||
|
||||
block->data = tmp;
|
||||
block->offset = 0;
|
||||
block->used_size = 0;
|
||||
block->block_size = size;
|
||||
|
||||
session_mapping = mapping;
|
||||
list_add_tail( &session.blocks, &block->entry );
|
||||
}
|
||||
|
||||
static struct session_block *grow_session_mapping( mem_size_t needed )
|
||||
{
|
||||
mem_size_t old_size = session_mapping->size, new_size;
|
||||
struct session_block *block;
|
||||
int unix_fd;
|
||||
void *tmp;
|
||||
|
||||
new_size = max( old_size * 3 / 2, old_size + max( needed, 0x10000 ) );
|
||||
new_size = (new_size + page_mask) & ~((mem_size_t)page_mask);
|
||||
assert( new_size > old_size );
|
||||
|
||||
unix_fd = get_unix_fd( session_mapping->fd );
|
||||
if (!grow_file( unix_fd, new_size )) return NULL;
|
||||
|
||||
if (!(block = mem_alloc( sizeof(*block) ))) return NULL;
|
||||
if ((tmp = mmap( NULL, new_size - old_size, PROT_READ | PROT_WRITE, MAP_SHARED, unix_fd, old_size )) == MAP_FAILED)
|
||||
{
|
||||
file_set_error();
|
||||
free( block );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
block->data = tmp;
|
||||
block->offset = old_size;
|
||||
block->used_size = 0;
|
||||
block->block_size = new_size - old_size;
|
||||
|
||||
session_mapping->size = new_size;
|
||||
list_add_tail( &session.blocks, &block->entry );
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static struct session_block *find_free_session_block( mem_size_t size )
|
||||
{
|
||||
struct session_block *block;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( block, &session.blocks, struct session_block, entry )
|
||||
if (size < block->block_size && block->used_size < block->block_size - size) return block;
|
||||
|
||||
return grow_session_mapping( size );
|
||||
}
|
||||
|
||||
const volatile void *alloc_shared_object(void)
|
||||
{
|
||||
struct session_object *object;
|
||||
struct list *ptr;
|
||||
|
||||
if ((ptr = list_head( &session.free_objects )))
|
||||
{
|
||||
object = CONTAINING_RECORD( ptr, struct session_object, entry );
|
||||
list_remove( &object->entry );
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_size_t size = sizeof(*object);
|
||||
struct session_block *block;
|
||||
|
||||
if (!(block = find_free_session_block( size ))) return NULL;
|
||||
object = (struct session_object *)(block->data + block->used_size);
|
||||
object->offset = (char *)&object->obj - block->data;
|
||||
block->used_size += size;
|
||||
}
|
||||
|
||||
SHARED_WRITE_BEGIN( &object->obj.shm, object_shm_t )
|
||||
{
|
||||
/* mark the object data as uninitialized */
|
||||
mark_block_uninitialized( (void *)shared, sizeof(*shared) );
|
||||
CONTAINING_RECORD( shared, shared_object_t, shm )->id = ++session.last_object_id;
|
||||
}
|
||||
SHARED_WRITE_END;
|
||||
|
||||
return &object->obj.shm;
|
||||
}
|
||||
|
||||
void free_shared_object( const volatile void *object_shm )
|
||||
{
|
||||
struct session_object *object = CONTAINING_RECORD( object_shm, struct session_object, obj.shm );
|
||||
|
||||
SHARED_WRITE_BEGIN( &object->obj.shm, object_shm_t )
|
||||
{
|
||||
mark_block_noaccess( (void *)shared, sizeof(*shared) );
|
||||
CONTAINING_RECORD( shared, shared_object_t, shm )->id = 0;
|
||||
}
|
||||
SHARED_WRITE_END;
|
||||
|
||||
list_add_tail( &session.free_objects, &object->entry );
|
||||
}
|
||||
|
||||
obj_locator_t get_shared_object_locator( const volatile void *object_shm )
|
||||
{
|
||||
struct session_object *object = CONTAINING_RECORD( object_shm, struct session_object, obj.shm );
|
||||
obj_locator_t locator = {.offset = object->offset, .id = object->obj.id};
|
||||
return locator;
|
||||
}
|
||||
|
||||
struct object *create_user_data_mapping( struct object *root, const struct unicode_str *name,
|
||||
unsigned int attr, const struct security_descriptor *sd )
|
||||
{
|
||||
|
|
|
@ -102,8 +102,19 @@ void close_objects(void)
|
|||
|
||||
/*****************************************************************/
|
||||
|
||||
/* mark a block of memory as not accessible for debugging purposes */
|
||||
void mark_block_noaccess( void *ptr, size_t size )
|
||||
{
|
||||
memset( ptr, 0xfe, size );
|
||||
#if defined(VALGRIND_MAKE_MEM_NOACCESS)
|
||||
VALGRIND_DISCARD( VALGRIND_MAKE_MEM_NOACCESS( ptr, size ) );
|
||||
#elif defined(VALGRIND_MAKE_NOACCESS)
|
||||
VALGRIND_DISCARD( VALGRIND_MAKE_NOACCESS( ptr, size ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* mark a block of memory as uninitialized for debugging purposes */
|
||||
static inline void mark_block_uninitialized( void *ptr, size_t size )
|
||||
void mark_block_uninitialized( void *ptr, size_t size )
|
||||
{
|
||||
memset( ptr, 0x55, size );
|
||||
#if defined(VALGRIND_MAKE_MEM_UNDEFINED)
|
||||
|
|
|
@ -139,6 +139,8 @@ struct wait_queue_entry
|
|||
struct thread_wait *wait;
|
||||
};
|
||||
|
||||
extern void mark_block_noaccess( void *ptr, size_t size );
|
||||
extern void mark_block_uninitialized( void *ptr, size_t size );
|
||||
extern void *mem_alloc( size_t size ) __WINE_ALLOC_SIZE(1) __WINE_DEALLOC(free) __WINE_MALLOC;
|
||||
extern void *memdup( const void *data, size_t len ) __WINE_ALLOC_SIZE(2) __WINE_DEALLOC(free);
|
||||
extern void *alloc_object( const struct object_ops *ops );
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef unsigned __int64 mem_size_t;
|
|||
typedef unsigned __int64 file_pos_t;
|
||||
typedef unsigned __int64 client_ptr_t;
|
||||
typedef unsigned __int64 affinity_t;
|
||||
typedef unsigned __int64 object_id_t;
|
||||
typedef client_ptr_t mod_handle_t;
|
||||
|
||||
struct request_header
|
||||
|
@ -895,6 +896,39 @@ struct directory_entry
|
|||
/* VARARG(type,unicode_str,type_len); */
|
||||
};
|
||||
|
||||
/****************************************************************/
|
||||
/* shared session mapping structures */
|
||||
|
||||
struct shared_cursor
|
||||
{
|
||||
int x; /* cursor position */
|
||||
int y;
|
||||
unsigned int last_change; /* time of last position change */
|
||||
};
|
||||
|
||||
typedef volatile struct
|
||||
{
|
||||
struct shared_cursor cursor; /* global cursor information */
|
||||
} desktop_shm_t;
|
||||
|
||||
typedef volatile union
|
||||
{
|
||||
desktop_shm_t desktop;
|
||||
} object_shm_t;
|
||||
|
||||
typedef volatile struct
|
||||
{
|
||||
LONG64 seq; /* sequence number - server updating if (seq & 1) != 0 */
|
||||
object_id_t id; /* object unique id, object data is valid if != 0 */
|
||||
object_shm_t shm; /* object shared data */
|
||||
} shared_object_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
object_id_t id; /* object unique id, object data is valid if != 0 */
|
||||
mem_size_t offset; /* offset of the object in session shared memory */
|
||||
} obj_locator_t;
|
||||
|
||||
/****************************************************************/
|
||||
/* Request declarations */
|
||||
|
||||
|
@ -2792,13 +2826,16 @@ enum coords_relative
|
|||
@REQ(get_thread_desktop)
|
||||
thread_id_t tid; /* thread id */
|
||||
@REPLY
|
||||
obj_handle_t handle; /* handle to the desktop */
|
||||
obj_locator_t locator; /* locator for the shared session object */
|
||||
obj_handle_t handle; /* handle to the desktop */
|
||||
@END
|
||||
|
||||
|
||||
/* Set the thread current desktop */
|
||||
@REQ(set_thread_desktop)
|
||||
obj_handle_t handle; /* handle to the desktop */
|
||||
@REPLY
|
||||
obj_locator_t locator; /* locator for the shared session object */
|
||||
@END
|
||||
|
||||
|
||||
|
|
|
@ -419,6 +419,7 @@ static void queue_cursor_message( struct desktop *desktop, user_handle_t win, un
|
|||
lparam_t wparam, lparam_t lparam )
|
||||
{
|
||||
static const struct hw_msg_source source = { IMDT_UNAVAILABLE, IMO_SYSTEM };
|
||||
const desktop_shm_t *desktop_shm = desktop->shared;
|
||||
struct thread_input *input;
|
||||
struct message *msg;
|
||||
|
||||
|
@ -427,8 +428,8 @@ static void queue_cursor_message( struct desktop *desktop, user_handle_t win, un
|
|||
msg->msg = message;
|
||||
msg->wparam = wparam;
|
||||
msg->lparam = lparam;
|
||||
msg->x = desktop->cursor.x;
|
||||
msg->y = desktop->cursor.y;
|
||||
msg->x = desktop_shm->cursor.x;
|
||||
msg->y = desktop_shm->cursor.y;
|
||||
if (!(msg->win = win) && (input = desktop->foreground_input)) msg->win = input->active;
|
||||
queue_hardware_message( desktop, msg, 1 );
|
||||
}
|
||||
|
@ -466,14 +467,21 @@ static int update_desktop_cursor_window( struct desktop *desktop, user_handle_t
|
|||
|
||||
static int update_desktop_cursor_pos( struct desktop *desktop, user_handle_t win, int x, int y )
|
||||
{
|
||||
const desktop_shm_t *desktop_shm = desktop->shared;
|
||||
int updated;
|
||||
unsigned int time = get_tick_count();
|
||||
|
||||
x = max( min( x, desktop->cursor.clip.right - 1 ), desktop->cursor.clip.left );
|
||||
y = max( min( y, desktop->cursor.clip.bottom - 1 ), desktop->cursor.clip.top );
|
||||
updated = (desktop->cursor.x != x || desktop->cursor.y != y);
|
||||
desktop->cursor.x = x;
|
||||
desktop->cursor.y = y;
|
||||
desktop->cursor.last_change = get_tick_count();
|
||||
|
||||
SHARED_WRITE_BEGIN( desktop_shm, desktop_shm_t )
|
||||
{
|
||||
updated = shared->cursor.x != x || shared->cursor.y != y;
|
||||
shared->cursor.x = x;
|
||||
shared->cursor.y = y;
|
||||
shared->cursor.last_change = time;
|
||||
}
|
||||
SHARED_WRITE_END;
|
||||
|
||||
if (!win || !is_window_visible( win ) || is_window_transparent( win ))
|
||||
win = shallow_window_from_point( desktop, x, y );
|
||||
|
@ -518,15 +526,17 @@ static void set_cursor_pos( struct desktop *desktop, int x, int y )
|
|||
static void get_message_defaults( struct msg_queue *queue, int *x, int *y, unsigned int *time )
|
||||
{
|
||||
struct desktop *desktop = queue->input->desktop;
|
||||
const desktop_shm_t *desktop_shm = desktop->shared;
|
||||
|
||||
*x = desktop->cursor.x;
|
||||
*y = desktop->cursor.y;
|
||||
*x = desktop_shm->cursor.x;
|
||||
*y = desktop_shm->cursor.y;
|
||||
*time = get_tick_count();
|
||||
}
|
||||
|
||||
/* set the cursor clip rectangle */
|
||||
void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, unsigned int flags, int reset )
|
||||
{
|
||||
const desktop_shm_t *desktop_shm = desktop->shared;
|
||||
rectangle_t top_rect;
|
||||
unsigned int old_flags;
|
||||
int x, y;
|
||||
|
@ -548,9 +558,9 @@ void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, unsig
|
|||
desktop->cursor.clip_flags = flags;
|
||||
|
||||
/* warp the mouse to be inside the clip rect */
|
||||
x = max( min( desktop->cursor.x, desktop->cursor.clip.right - 1 ), desktop->cursor.clip.left );
|
||||
y = max( min( desktop->cursor.y, desktop->cursor.clip.bottom - 1 ), desktop->cursor.clip.top );
|
||||
if (x != desktop->cursor.x || y != desktop->cursor.y) set_cursor_pos( desktop, x, y );
|
||||
x = max( min( desktop_shm->cursor.x, desktop->cursor.clip.right - 1 ), desktop->cursor.clip.left );
|
||||
y = max( min( desktop_shm->cursor.y, desktop->cursor.clip.bottom - 1 ), desktop->cursor.clip.top );
|
||||
if (x != desktop_shm->cursor.x || y != desktop_shm->cursor.y) set_cursor_pos( desktop, x, y );
|
||||
|
||||
/* request clip cursor rectangle reset to the desktop thread */
|
||||
if (reset) post_desktop_message( desktop, WM_WINE_CLIPCURSOR, flags, FALSE );
|
||||
|
@ -1672,6 +1682,7 @@ static unsigned int get_rawinput_device_flags( struct process *process, struct m
|
|||
/* queue a hardware message into a given thread input */
|
||||
static void queue_hardware_message( struct desktop *desktop, struct message *msg, int always_queue )
|
||||
{
|
||||
const desktop_shm_t *desktop_shm = desktop->shared;
|
||||
user_handle_t win;
|
||||
struct thread *thread;
|
||||
struct thread_input *input;
|
||||
|
@ -1705,8 +1716,8 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg
|
|||
if (desktop->keystate[VK_XBUTTON2] & 0x80) msg->wparam |= MK_XBUTTON2;
|
||||
break;
|
||||
}
|
||||
msg->x = desktop->cursor.x;
|
||||
msg->y = desktop->cursor.y;
|
||||
msg->x = desktop_shm->cursor.x;
|
||||
msg->y = desktop_shm->cursor.y;
|
||||
|
||||
if (msg->win && (thread = get_window_thread( msg->win )))
|
||||
{
|
||||
|
@ -1982,11 +1993,12 @@ static void dispatch_rawinput_message( struct desktop *desktop, struct rawinput_
|
|||
static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
|
||||
unsigned int origin, struct msg_queue *sender )
|
||||
{
|
||||
const desktop_shm_t *desktop_shm = desktop->shared;
|
||||
struct hardware_msg_data *msg_data;
|
||||
struct rawinput_message raw_msg;
|
||||
struct message *msg;
|
||||
struct thread *foreground;
|
||||
unsigned int i, time, flags;
|
||||
unsigned int i, time = get_tick_count(), flags;
|
||||
struct hw_msg_source source = { IMDT_MOUSE, origin };
|
||||
lparam_t wparam = input->mouse.data << 16;
|
||||
int wait = 0, x, y;
|
||||
|
@ -2008,10 +2020,15 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
|
|||
WM_MOUSEHWHEEL /* 0x1000 = MOUSEEVENTF_HWHEEL */
|
||||
};
|
||||
|
||||
desktop->cursor.last_change = get_tick_count();
|
||||
SHARED_WRITE_BEGIN( desktop_shm, desktop_shm_t )
|
||||
{
|
||||
shared->cursor.last_change = time;
|
||||
}
|
||||
SHARED_WRITE_END;
|
||||
|
||||
flags = input->mouse.flags;
|
||||
time = input->mouse.time;
|
||||
if (!time) time = desktop->cursor.last_change;
|
||||
if (!time) time = desktop_shm->cursor.last_change;
|
||||
|
||||
if (flags & MOUSEEVENTF_MOVE)
|
||||
{
|
||||
|
@ -2020,19 +2037,19 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
|
|||
x = input->mouse.x;
|
||||
y = input->mouse.y;
|
||||
if (flags & ~(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE) &&
|
||||
x == desktop->cursor.x && y == desktop->cursor.y)
|
||||
x == desktop_shm->cursor.x && y == desktop_shm->cursor.y)
|
||||
flags &= ~MOUSEEVENTF_MOVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = desktop->cursor.x + input->mouse.x;
|
||||
y = desktop->cursor.y + input->mouse.y;
|
||||
x = desktop_shm->cursor.x + input->mouse.x;
|
||||
y = desktop_shm->cursor.y + input->mouse.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x = desktop->cursor.x;
|
||||
y = desktop->cursor.y;
|
||||
x = desktop_shm->cursor.x;
|
||||
y = desktop_shm->cursor.y;
|
||||
}
|
||||
|
||||
if ((foreground = get_foreground_thread( desktop, win )))
|
||||
|
@ -2043,7 +2060,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
|
|||
raw_msg.time = time;
|
||||
raw_msg.message = WM_INPUT;
|
||||
raw_msg.flags = flags;
|
||||
rawmouse_init( &raw_msg.rawinput, &raw_msg.data.mouse, x - desktop->cursor.x, y - desktop->cursor.y,
|
||||
rawmouse_init( &raw_msg.rawinput, &raw_msg.data.mouse, x - desktop_shm->cursor.x, y - desktop_shm->cursor.y,
|
||||
raw_msg.flags, input->mouse.data, input->mouse.info );
|
||||
|
||||
dispatch_rawinput_message( desktop, &raw_msg );
|
||||
|
@ -2293,6 +2310,7 @@ static void queue_pointer_message( struct pointer *pointer, int repeated )
|
|||
};
|
||||
struct hw_msg_source source = { IMDT_UNAVAILABLE, IMDT_TOUCH };
|
||||
struct desktop *desktop = pointer->desktop;
|
||||
const desktop_shm_t *desktop_shm = desktop->shared;
|
||||
const hw_input_t *input = &pointer->input;
|
||||
unsigned int i, wparam = input->hw.wparam;
|
||||
timeout_t time = get_tick_count();
|
||||
|
@ -2315,8 +2333,8 @@ static void queue_pointer_message( struct pointer *pointer, int repeated )
|
|||
msg->msg = messages[input->hw.msg - WM_POINTERUPDATE][i];
|
||||
msg->wparam = wparam;
|
||||
msg->lparam = MAKELONG(x, y);
|
||||
msg->x = desktop->cursor.x;
|
||||
msg->y = desktop->cursor.y;
|
||||
msg->x = desktop_shm->cursor.x;
|
||||
msg->y = desktop_shm->cursor.y;
|
||||
|
||||
queue_hardware_message( desktop, msg, 1 );
|
||||
}
|
||||
|
@ -2371,6 +2389,7 @@ static struct pointer *find_pointer_from_id( struct desktop *desktop, unsigned i
|
|||
static void queue_custom_hardware_message( struct desktop *desktop, user_handle_t win,
|
||||
unsigned int origin, const hw_input_t *input )
|
||||
{
|
||||
const desktop_shm_t *desktop_shm = desktop->shared;
|
||||
struct hw_msg_source source = { IMDT_UNAVAILABLE, origin };
|
||||
struct thread *foreground;
|
||||
struct pointer *pointer;
|
||||
|
@ -2415,8 +2434,8 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
|
|||
msg->msg = input->hw.msg;
|
||||
msg->wparam = input->hw.wparam;
|
||||
msg->lparam = input->hw.lparam;
|
||||
msg->x = desktop->cursor.x;
|
||||
msg->y = desktop->cursor.y;
|
||||
msg->x = desktop_shm->cursor.x;
|
||||
msg->y = desktop_shm->cursor.y;
|
||||
|
||||
queue_hardware_message( desktop, msg, 1 );
|
||||
}
|
||||
|
@ -2964,6 +2983,7 @@ DECL_HANDLER(send_hardware_message)
|
|||
struct desktop *desktop;
|
||||
unsigned int origin = (req->flags & SEND_HWMSG_INJECTED ? IMO_INJECTED : IMO_HARDWARE);
|
||||
struct msg_queue *sender = req->flags & SEND_HWMSG_INJECTED ? get_current_queue() : NULL;
|
||||
const desktop_shm_t *desktop_shm;
|
||||
int wait = 0;
|
||||
|
||||
if (!(desktop = get_hardware_input_desktop( req->win ))) return;
|
||||
|
@ -2974,9 +2994,10 @@ DECL_HANDLER(send_hardware_message)
|
|||
set_error( STATUS_ACCESS_DENIED );
|
||||
return;
|
||||
}
|
||||
desktop_shm = desktop->shared;
|
||||
|
||||
reply->prev_x = desktop->cursor.x;
|
||||
reply->prev_y = desktop->cursor.y;
|
||||
reply->prev_x = desktop_shm->cursor.x;
|
||||
reply->prev_y = desktop_shm->cursor.y;
|
||||
|
||||
switch (req->input.type)
|
||||
{
|
||||
|
@ -2994,8 +3015,8 @@ DECL_HANDLER(send_hardware_message)
|
|||
}
|
||||
|
||||
reply->wait = sender ? wait : 0;
|
||||
reply->new_x = desktop->cursor.x;
|
||||
reply->new_y = desktop->cursor.y;
|
||||
reply->new_x = desktop_shm->cursor.x;
|
||||
reply->new_y = desktop_shm->cursor.y;
|
||||
release_object( desktop );
|
||||
}
|
||||
|
||||
|
@ -3688,16 +3709,18 @@ DECL_HANDLER(set_cursor)
|
|||
user_handle_t prev_cursor, new_cursor;
|
||||
struct thread_input *input;
|
||||
struct desktop *desktop;
|
||||
const desktop_shm_t *desktop_shm;
|
||||
|
||||
if (!queue) return;
|
||||
input = queue->input;
|
||||
desktop = input->desktop;
|
||||
desktop_shm = desktop->shared;
|
||||
prev_cursor = input->cursor_count < 0 ? 0 : input->cursor;
|
||||
|
||||
reply->prev_handle = input->cursor;
|
||||
reply->prev_count = input->cursor_count;
|
||||
reply->prev_x = desktop->cursor.x;
|
||||
reply->prev_y = desktop->cursor.y;
|
||||
reply->prev_x = desktop_shm->cursor.x;
|
||||
reply->prev_y = desktop_shm->cursor.y;
|
||||
|
||||
if (req->flags & SET_CURSOR_HANDLE)
|
||||
{
|
||||
|
@ -3720,10 +3743,10 @@ DECL_HANDLER(set_cursor)
|
|||
new_cursor = input->cursor_count < 0 ? 0 : input->cursor;
|
||||
if (prev_cursor != new_cursor) update_desktop_cursor_handle( desktop, input, new_cursor );
|
||||
|
||||
reply->new_x = desktop->cursor.x;
|
||||
reply->new_y = desktop->cursor.y;
|
||||
reply->new_x = desktop_shm->cursor.x;
|
||||
reply->new_y = desktop_shm->cursor.y;
|
||||
reply->new_clip = desktop->cursor.clip;
|
||||
reply->last_change = desktop->cursor.last_change;
|
||||
reply->last_change = desktop_shm->cursor.last_change;
|
||||
}
|
||||
|
||||
/* Get the history of the 64 last cursor positions */
|
||||
|
|
|
@ -721,6 +721,8 @@ C_ASSERT( sizeof(mem_size_t) == 8 );
|
|||
C_ASSERT( sizeof(message_data_t) == 48 );
|
||||
C_ASSERT( sizeof(mod_handle_t) == 8 );
|
||||
C_ASSERT( sizeof(obj_handle_t) == 4 );
|
||||
C_ASSERT( sizeof(obj_locator_t) == 16 );
|
||||
C_ASSERT( sizeof(object_id_t) == 8 );
|
||||
C_ASSERT( sizeof(pe_image_info_t) == 88 );
|
||||
C_ASSERT( sizeof(process_id_t) == 4 );
|
||||
C_ASSERT( sizeof(property_data_t) == 16 );
|
||||
|
@ -1744,10 +1746,13 @@ C_ASSERT( FIELD_OFFSET(struct close_desktop_request, handle) == 12 );
|
|||
C_ASSERT( sizeof(struct close_desktop_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_thread_desktop_request, tid) == 12 );
|
||||
C_ASSERT( sizeof(struct get_thread_desktop_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_thread_desktop_reply, handle) == 8 );
|
||||
C_ASSERT( sizeof(struct get_thread_desktop_reply) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_thread_desktop_reply, locator) == 8 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_thread_desktop_reply, handle) == 24 );
|
||||
C_ASSERT( sizeof(struct get_thread_desktop_reply) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_thread_desktop_request, handle) == 12 );
|
||||
C_ASSERT( sizeof(struct set_thread_desktop_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_thread_desktop_reply, locator) == 8 );
|
||||
C_ASSERT( sizeof(struct set_thread_desktop_reply) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct enum_desktop_request, winstation) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct enum_desktop_request, index) == 16 );
|
||||
C_ASSERT( sizeof(struct enum_desktop_request) == 24 );
|
||||
|
|
|
@ -467,6 +467,14 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input )
|
|||
}
|
||||
}
|
||||
|
||||
static void dump_obj_locator( const char *prefix, const obj_locator_t *locator )
|
||||
{
|
||||
fprintf( stderr, "%s{", prefix );
|
||||
dump_uint64( "id=", &locator->id );
|
||||
dump_uint64( ",offset=", &locator->offset );
|
||||
fprintf( stderr, "}" );
|
||||
}
|
||||
|
||||
static void dump_luid( const char *prefix, const struct luid *luid )
|
||||
{
|
||||
fprintf( stderr, "%s%d.%u", prefix, luid->high_part, luid->low_part );
|
||||
|
@ -3426,7 +3434,8 @@ static void dump_get_thread_desktop_request( const struct get_thread_desktop_req
|
|||
|
||||
static void dump_get_thread_desktop_reply( const struct get_thread_desktop_reply *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
dump_obj_locator( " locator=", &req->locator );
|
||||
fprintf( stderr, ", handle=%04x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_set_thread_desktop_request( const struct set_thread_desktop_request *req )
|
||||
|
@ -3434,6 +3443,11 @@ static void dump_set_thread_desktop_request( const struct set_thread_desktop_req
|
|||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_set_thread_desktop_reply( const struct set_thread_desktop_reply *req )
|
||||
{
|
||||
dump_obj_locator( " locator=", &req->locator );
|
||||
}
|
||||
|
||||
static void dump_enum_desktop_request( const struct enum_desktop_request *req )
|
||||
{
|
||||
fprintf( stderr, " winstation=%04x", req->winstation );
|
||||
|
@ -5101,7 +5115,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
NULL,
|
||||
NULL,
|
||||
(dump_func)dump_get_thread_desktop_reply,
|
||||
NULL,
|
||||
(dump_func)dump_set_thread_desktop_reply,
|
||||
(dump_func)dump_enum_desktop_reply,
|
||||
(dump_func)dump_set_user_object_info_reply,
|
||||
(dump_func)dump_register_hotkey_reply,
|
||||
|
|
|
@ -56,11 +56,8 @@ struct winstation
|
|||
|
||||
struct global_cursor
|
||||
{
|
||||
int x; /* cursor position */
|
||||
int y;
|
||||
rectangle_t clip; /* cursor clip rectangle */
|
||||
unsigned int clip_flags; /* last cursor clip flags */
|
||||
unsigned int last_change; /* time of last position change */
|
||||
user_handle_t win; /* window that contains the cursor */
|
||||
};
|
||||
|
||||
|
@ -93,6 +90,7 @@ struct desktop
|
|||
struct global_cursor cursor; /* global cursor information */
|
||||
unsigned char keystate[256]; /* asynchronous key state */
|
||||
struct key_repeat key_repeat; /* key auto-repeat */
|
||||
const desktop_shm_t *shared; /* desktop session shared memory */
|
||||
};
|
||||
|
||||
/* user handles functions */
|
||||
|
|
|
@ -298,6 +298,20 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned
|
|||
list_add_tail( &winstation->desktops, &desktop->entry );
|
||||
list_init( &desktop->hotkeys );
|
||||
list_init( &desktop->pointers );
|
||||
|
||||
if (!(desktop->shared = alloc_shared_object()))
|
||||
{
|
||||
release_object( desktop );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SHARED_WRITE_BEGIN( desktop->shared, desktop_shm_t )
|
||||
{
|
||||
shared->cursor.x = 0;
|
||||
shared->cursor.y = 0;
|
||||
shared->cursor.last_change = 0;
|
||||
}
|
||||
SHARED_WRITE_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -368,6 +382,7 @@ static void desktop_destroy( struct object *obj )
|
|||
if (desktop->close_timeout) remove_timeout_user( desktop->close_timeout );
|
||||
if (desktop->key_repeat.timeout) remove_timeout_user( desktop->key_repeat.timeout );
|
||||
release_object( desktop->winstation );
|
||||
if (desktop->shared) free_shared_object( desktop->shared );
|
||||
}
|
||||
|
||||
/* retrieve the thread desktop, checking the handle access rights */
|
||||
|
@ -735,10 +750,19 @@ DECL_HANDLER(close_desktop)
|
|||
/* get the thread current desktop */
|
||||
DECL_HANDLER(get_thread_desktop)
|
||||
{
|
||||
struct desktop *desktop;
|
||||
struct thread *thread;
|
||||
|
||||
if (!(thread = get_thread_from_id( req->tid ))) return;
|
||||
reply->handle = thread->desktop;
|
||||
|
||||
if (!(desktop = get_thread_desktop( thread, 0 ))) clear_error();
|
||||
else
|
||||
{
|
||||
if (desktop->shared) reply->locator = get_shared_object_locator( desktop->shared );
|
||||
release_object( desktop );
|
||||
}
|
||||
|
||||
release_object( thread );
|
||||
}
|
||||
|
||||
|
@ -781,6 +805,7 @@ DECL_HANDLER(set_thread_desktop)
|
|||
if (old_desktop) remove_desktop_thread( old_desktop, current );
|
||||
add_desktop_thread( new_desktop, current );
|
||||
}
|
||||
reply->locator = get_shared_object_locator( new_desktop->shared );
|
||||
}
|
||||
|
||||
if (!current->process->desktop)
|
||||
|
|
|
@ -42,6 +42,7 @@ my %formats =
|
|||
"file_pos_t" => [ 8, 8, "&dump_uint64" ],
|
||||
"mem_size_t" => [ 8, 8, "&dump_uint64" ],
|
||||
"affinity_t" => [ 8, 8, "&dump_uint64" ],
|
||||
"object_id_t" => [ 8, 8, "&dump_uint64" ],
|
||||
"timeout_t" => [ 8, 8, "&dump_timeout" ],
|
||||
"abstime_t" => [ 8, 8, "&dump_abstime" ],
|
||||
"rectangle_t" => [ 16, 4, "&dump_rectangle" ],
|
||||
|
@ -52,6 +53,7 @@ my %formats =
|
|||
"generic_map_t" => [ 16, 4, "&dump_generic_map" ],
|
||||
"ioctl_code_t" => [ 4, 4, "&dump_ioctl_code" ],
|
||||
"hw_input_t" => [ 40, 8, "&dump_hw_input" ],
|
||||
"obj_locator_t" => [ 16, 8, "&dump_obj_locator" ],
|
||||
# varargs-only structures
|
||||
"apc_call_t" => [ 64, 8 ],
|
||||
"context_t" => [ 1728, 8 ],
|
||||
|
|
Loading…
Reference in a new issue