Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
[PATCH 3/4] nsiproxy: Implement Wow64 NSI entry points in the Unix library.
by Huw Davies
From: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/nsiproxy.sys/nsi.c | 131 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 131 insertions(+)
diff --git a/dlls/nsiproxy.sys/nsi.c b/dlls/nsiproxy.sys/nsi.c
index b9b04e63545..84fbf268254 100644
--- a/dlls/nsiproxy.sys/nsi.c
+++ b/dlls/nsiproxy.sys/nsi.c
@@ -155,3 +155,134 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
unix_nsi_get_all_parameters_ex,
unix_nsi_get_parameter_ex
};
+
+#ifdef _WIN64
+
+typedef UINT PTR32;
+
+static NTSTATUS wow64_nsi_enumerate_all_ex( void *args )
+{
+ struct
+ {
+ PTR32 unknown[2];
+ PTR32 module;
+ UINT table;
+ UINT first_arg;
+ UINT second_arg;
+ PTR32 key_data;
+ UINT key_size;
+ PTR32 rw_data;
+ UINT rw_size;
+ PTR32 dynamic_data;
+ UINT dynamic_size;
+ PTR32 static_data;
+ UINT static_size;
+ UINT count;
+ } *params32 = args;
+ struct nsi_enumerate_all_ex params =
+ {
+ .unknown[0] = ULongToPtr( params32->unknown[0] ),
+ .unknown[1] = ULongToPtr( params32->unknown[1] ),
+ .module = ULongToPtr( params32->module ),
+ .table = params32->table,
+ .first_arg = params32->first_arg,
+ .second_arg = params32->second_arg,
+ .key_data = ULongToPtr( params32->key_data ),
+ .key_size = params32->key_size,
+ .rw_data = ULongToPtr( params32->rw_data ),
+ .rw_size = params32->rw_size,
+ .dynamic_data = ULongToPtr( params32->dynamic_data ),
+ .dynamic_size = params32->dynamic_size,
+ .static_data = ULongToPtr( params32->static_data ),
+ .static_size = params32->static_size,
+ .count = params32->count
+ };
+ NTSTATUS status = nsi_enumerate_all_ex( ¶ms );
+ params32->count = params.count;
+ return status;
+}
+
+static NTSTATUS wow64_nsi_get_all_parameters_ex( void *args )
+{
+ struct
+ {
+ PTR32 unknown[2];
+ PTR32 module;
+ UINT table;
+ UINT first_arg;
+ UINT unknown2;
+ PTR32 key;
+ UINT key_size;
+ PTR32 rw_data;
+ UINT rw_size;
+ PTR32 dynamic_data;
+ UINT dynamic_size;
+ PTR32 static_data;
+ UINT static_size;
+ } const *params32 = args;
+ struct nsi_get_all_parameters_ex params =
+ {
+ .unknown[0] = ULongToPtr( params32->unknown[0] ),
+ .unknown[1] = ULongToPtr( params32->unknown[1] ),
+ .module = ULongToPtr( params32->module ),
+ .table = params32->table,
+ .first_arg = params32->first_arg,
+ .unknown2 = params32->unknown2,
+ .key = ULongToPtr( params32->key ),
+ .key_size = params32->key_size,
+ .rw_data = ULongToPtr( params32->rw_data ),
+ .rw_size = params32->rw_size,
+ .dynamic_data = ULongToPtr( params32->dynamic_data ),
+ .dynamic_size = params32->dynamic_size,
+ .static_data = ULongToPtr( params32->static_data ),
+ .static_size = params32->static_size
+ };
+ return nsi_get_all_parameters_ex( ¶ms );
+}
+
+static NTSTATUS wow64_nsi_get_parameter_ex( void *args )
+{
+ struct
+ {
+ PTR32 unknown[2];
+ PTR32 module;
+ UINT table;
+ UINT first_arg;
+ UINT unknown2;
+ PTR32 key;
+ UINT key_size;
+ UINT param_type;
+ PTR32 data;
+ UINT data_size;
+ UINT data_offset;
+ } const *params32 = args;
+ struct nsi_get_parameter_ex params =
+ {
+ .unknown[0] = ULongToPtr( params32->unknown[0] ),
+ .unknown[1] = ULongToPtr( params32->unknown[1] ),
+ .module = ULongToPtr( params32->module ),
+ .table = params32->table,
+ .first_arg = params32->first_arg,
+ .unknown2 = params32->unknown2,
+ .key = ULongToPtr( params32->key ),
+ .key_size = params32->key_size,
+ .param_type = params32->param_type,
+ .data = ULongToPtr( params32->data ),
+ .data_size = params32->data_size,
+ .data_offset = params32->data_offset
+ };
+ return nsi_get_parameter_ex( ¶ms );
+}
+
+const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
+{
+ icmp_cancel_listen,
+ icmp_close,
+ icmp_listen,
+ icmp_send_echo,
+ wow64_nsi_enumerate_all_ex,
+ wow64_nsi_get_all_parameters_ex,
+ wow64_nsi_get_parameter_ex
+};
+
+#endif /* _WIN64 */
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/292
June 21, 2022
[PATCH 2/4] nsiproxy: Pass a ptr to receive the ICMP handle.
by Huw Davies
From: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/nsiproxy.sys/device.c | 4 +++-
dlls/nsiproxy.sys/icmp_echo.c | 6 +++---
dlls/nsiproxy.sys/nsiproxy_private.h | 2 +-
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/dlls/nsiproxy.sys/device.c b/dlls/nsiproxy.sys/device.c
index aa030fa459c..7aba1f0c36f 100644
--- a/dlls/nsiproxy.sys/device.c
+++ b/dlls/nsiproxy.sys/device.c
@@ -366,6 +366,7 @@ static void handle_queued_send_echo( IRP *irp )
{
struct nsiproxy_icmp_echo *in = (struct nsiproxy_icmp_echo *)irp->AssociatedIrp.SystemBuffer;
struct icmp_send_echo_params params;
+ icmp_handle handle;
NTSTATUS status;
TRACE( "\n" );
@@ -376,6 +377,7 @@ static void handle_queued_send_echo( IRP *irp )
params.ttl = in->ttl;
params.tos = in->tos;
params.dst = &in->dst;
+ params.handle = &handle;
status = nsiproxy_call( icmp_send_echo, ¶ms );
TRACE( "icmp_send_echo rets %08lx\n", status );
@@ -389,7 +391,7 @@ static void handle_queued_send_echo( IRP *irp )
}
else
{
- irp_set_icmp_handle( irp, params.handle );
+ irp_set_icmp_handle( irp, handle );
RtlQueueWorkItem( listen_thread_proc, irp, WT_EXECUTELONGFUNCTION );
}
}
diff --git a/dlls/nsiproxy.sys/icmp_echo.c b/dlls/nsiproxy.sys/icmp_echo.c
index dda19915fe7..e92fa4394c1 100644
--- a/dlls/nsiproxy.sys/icmp_echo.c
+++ b/dlls/nsiproxy.sys/icmp_echo.c
@@ -659,9 +659,9 @@ NTSTATUS icmp_send_echo( void *args )
return STATUS_SUCCESS;
}
- params->handle = handle_alloc( data );
- if (!params->handle) icmp_data_free( data );
- return params->handle ? STATUS_PENDING : STATUS_NO_MEMORY;
+ *params->handle = handle_alloc( data );
+ if (!*params->handle) icmp_data_free( data );
+ return *params->handle ? STATUS_PENDING : STATUS_NO_MEMORY;
}
static int get_timeout( LARGE_INTEGER start, UINT timeout )
diff --git a/dlls/nsiproxy.sys/nsiproxy_private.h b/dlls/nsiproxy.sys/nsiproxy_private.h
index a62a0eebda8..241106fe228 100644
--- a/dlls/nsiproxy.sys/nsiproxy_private.h
+++ b/dlls/nsiproxy.sys/nsiproxy_private.h
@@ -45,7 +45,7 @@ struct icmp_send_echo_params
void *request, *reply;
UINT request_size, reply_len;
BYTE bits, ttl, tos;
- icmp_handle handle;
+ icmp_handle *handle;
};
/* output for IOCTL_NSIPROXY_WINE_ICMP_ECHO - cf. ICMP_ECHO_REPLY */
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/292
June 21, 2022
[PATCH 1/4] nsiproxy: Use an unsigned integer for the ICMP handles.
by Huw Davies
From: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/nsiproxy.sys/device.c | 19 ++++++++++-------
dlls/nsiproxy.sys/icmp_echo.c | 32 +++++++++++++---------------
dlls/nsiproxy.sys/nsiproxy_private.h | 17 +++++++++++++--
3 files changed, 41 insertions(+), 27 deletions(-)
diff --git a/dlls/nsiproxy.sys/device.c b/dlls/nsiproxy.sys/device.c
index d3845829a85..aa030fa459c 100644
--- a/dlls/nsiproxy.sys/device.c
+++ b/dlls/nsiproxy.sys/device.c
@@ -180,19 +180,20 @@ static NTSTATUS nsiproxy_get_parameter( IRP *irp )
return status;
}
-static inline HANDLE irp_get_icmp_handle( IRP *irp )
+static inline icmp_handle irp_get_icmp_handle( IRP *irp )
{
- return irp->Tail.Overlay.DriverContext[0];
+ return PtrToUlong( irp->Tail.Overlay.DriverContext[0] );
}
-static inline HANDLE irp_set_icmp_handle( IRP *irp, HANDLE handle )
+static inline icmp_handle irp_set_icmp_handle( IRP *irp, icmp_handle handle )
{
- return InterlockedExchangePointer( irp->Tail.Overlay.DriverContext, handle );
+ return PtrToUlong( InterlockedExchangePointer( irp->Tail.Overlay.DriverContext,
+ ULongToPtr( handle ) ) );
}
static void WINAPI icmp_echo_cancel( DEVICE_OBJECT *device, IRP *irp )
{
- HANDLE handle;
+ struct icmp_cancel_listen_params params;
TRACE( "device %p, irp %p.\n", device, irp );
@@ -205,8 +206,8 @@ static void WINAPI icmp_echo_cancel( DEVICE_OBJECT *device, IRP *irp )
cancel it, or the irp has already finished. If the handle
does exist then notify the listen thread. In all cases the irp
will be completed elsewhere. */
- handle = irp_get_icmp_handle( irp );
- if (handle) nsiproxy_call( icmp_cancel_listen, handle );
+ params.handle = irp_get_icmp_handle( irp );
+ if (params.handle) nsiproxy_call( icmp_cancel_listen, ¶ms );
LeaveCriticalSection( &nsiproxy_cs );
}
@@ -328,6 +329,7 @@ static DWORD WINAPI listen_thread_proc( void *arg )
IRP *irp = arg;
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
struct nsiproxy_icmp_echo *in = irp->AssociatedIrp.SystemBuffer;
+ struct icmp_close_params close_params;
struct icmp_listen_params params;
NTSTATUS status;
@@ -345,7 +347,8 @@ static DWORD WINAPI listen_thread_proc( void *arg )
EnterCriticalSection( &nsiproxy_cs );
- nsiproxy_call( icmp_close, irp_set_icmp_handle( irp, NULL ) );
+ close_params.handle = irp_set_icmp_handle( irp, 0 );
+ nsiproxy_call( icmp_close, &close_params );
irp->IoStatus.Status = status;
if (status == STATUS_SUCCESS)
diff --git a/dlls/nsiproxy.sys/icmp_echo.c b/dlls/nsiproxy.sys/icmp_echo.c
index c3ce841c003..dda19915fe7 100644
--- a/dlls/nsiproxy.sys/icmp_echo.c
+++ b/dlls/nsiproxy.sys/icmp_echo.c
@@ -120,10 +120,10 @@ static struct icmp_data *handle_table[MAX_HANDLES];
static pthread_mutex_t handle_lock = PTHREAD_MUTEX_INITIALIZER;
static struct icmp_data **next_free, **next_unused = handle_table;
-static HANDLE handle_alloc( struct icmp_data *data )
+static icmp_handle handle_alloc( struct icmp_data *data )
{
struct icmp_data **entry;
- HANDLE h;
+ icmp_handle h;
pthread_mutex_lock( &handle_lock );
entry = next_free;
@@ -136,25 +136,23 @@ static HANDLE handle_alloc( struct icmp_data *data )
return 0;
}
*entry = data;
- h = LongToHandle( entry - handle_table + 1 );
+ h = entry - handle_table + 1;
pthread_mutex_unlock( &handle_lock );
- TRACE( "returning handle %p\n", h );
+ TRACE( "returning handle %x\n", h );
return h;
}
-static struct icmp_data **handle_entry( HANDLE h )
+static struct icmp_data **handle_entry( icmp_handle h )
{
- unsigned int idx = HandleToLong( h );
-
- if (!idx || idx > MAX_HANDLES)
+ if (!h || h > MAX_HANDLES)
{
ERR( "Invalid icmp handle\n" );
return NULL;
}
- return handle_table + idx - 1;
+ return handle_table + h - 1;
}
-static struct icmp_data *handle_data( HANDLE h )
+static struct icmp_data *handle_data( icmp_handle h )
{
struct icmp_data **entry = handle_entry( h );
@@ -162,11 +160,11 @@ static struct icmp_data *handle_data( HANDLE h )
return *entry;
}
-static void handle_free( HANDLE h )
+static void handle_free( icmp_handle h )
{
struct icmp_data **entry;
- TRACE( "%p\n", h );
+ TRACE( "%x\n", h );
pthread_mutex_lock( &handle_lock );
entry = handle_entry( h );
if (entry)
@@ -778,8 +776,8 @@ NTSTATUS icmp_listen( void *args )
NTSTATUS icmp_cancel_listen( void *args )
{
- HANDLE handle = args;
- struct icmp_data *data = handle_data( handle );
+ struct icmp_cancel_listen_params *params = args;
+ struct icmp_data *data = handle_data( params->handle );
if (!data) return STATUS_INVALID_PARAMETER;
write( data->cancel_pipe[1], "x", 1 );
@@ -788,11 +786,11 @@ NTSTATUS icmp_cancel_listen( void *args )
NTSTATUS icmp_close( void *args )
{
- HANDLE handle = args;
- struct icmp_data *data = handle_data( handle );
+ struct icmp_close_params *params = args;
+ struct icmp_data *data = handle_data( params->handle );
if (!data) return STATUS_INVALID_PARAMETER;
icmp_data_free( data );
- handle_free( handle );
+ handle_free( params->handle );
return STATUS_SUCCESS;
}
diff --git a/dlls/nsiproxy.sys/nsiproxy_private.h b/dlls/nsiproxy.sys/nsiproxy_private.h
index 4bd269a0691..a62a0eebda8 100644
--- a/dlls/nsiproxy.sys/nsiproxy_private.h
+++ b/dlls/nsiproxy.sys/nsiproxy_private.h
@@ -17,9 +17,22 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
+typedef UINT icmp_handle;
+
+struct icmp_cancel_listen_params
+{
+ icmp_handle handle;
+};
+
+struct icmp_close_params
+{
+ icmp_handle handle;
+};
+
struct icmp_listen_params
{
- HANDLE handle;
+ icmp_handle handle;
void *reply;
ULONGLONG user_reply_ptr;
unsigned int bits, reply_len;
@@ -32,7 +45,7 @@ struct icmp_send_echo_params
void *request, *reply;
UINT request_size, reply_len;
BYTE bits, ttl, tos;
- HANDLE handle;
+ icmp_handle handle;
};
/* output for IOCTL_NSIPROXY_WINE_ICMP_ECHO - cf. ICMP_ECHO_REPLY */
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/292
June 21, 2022
[PATCH 0/4] MR292: nsiproxy: Add wow64 entry points
by Huw Davies (@huw)
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/292
June 21, 2022
Re: [PATCH 1/1] d3drm: Implement IDirect3DRMFrame2::SetSceneBackgroundImage
by Stefan Dösinger
> Am 21.06.2022 um 09:44 schrieb Alistair Leslie-Hughes <wine(a)gitlab.winehq.org>:
>
> + if (frame->backgroundimage)
> + IDirect3DRMTexture3_Release(frame->backgroundimage);
> + frame->backgroundimage = texture;
> + if (frame->backgroundimage)
> + IDirect3DRMTexture3_AddRef(frame->backgroundimage);
It is better to addref the new one before releasing the old one. In the current code you might destroy the image when the application is redundantly re-setting the current image and the only remaining reference is held by the d3drm frame.
> + struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
> + TRACE("iface %p, texture %p\n", iface, texture);
> + return d3drm_frame3_SetSceneBackgroundImage(&frame->IDirect3DRMFrame3_iface, (IDirect3DRMTexture3*)texture);
This seems wrong, IDirect3DRMTexture3 and IDirect3DRMTexture2 (same for texture1) are different interfaces and have different vtable members in d3drm_texture. Later code that does impl_from_IDirect3DRMTexture3 will get a wrong implementation pointer.
What you can do here depends on a few things. It also ties to this line of code here:
> +++ b/dlls/d3drm/d3drm_private.h
> @@ -81,6 +81,7 @@ struct d3drm_frame
> IDirect3DRMFrame3 IDirect3DRMFrame3_iface;
> IDirect3DRM *d3drm;
> LONG ref;
> + IDirect3DRMTexture3 *backgroundimage;
If you need to be able to accept "wrong" texture versions and return the interface the application passed back to the application in GetBackgroundImage you can store the assigned texture as IUnknown or IDirect3DRMObject *. Then whenever some code accesses the texture methods it needs to QI the version it wants to call. If it needs the members, QI to a known version, then impl_from_IDirect3DRMTextureX. This option - store the interface - is especially the way to go if you might deal with interface implementations different from ours, i.e. if the application has its own implementation of d3drm textures and expects you to work with them.
Otherwise you can get the struct d3drm_texture from the version passed in in each of the SetSceneBackgroundImage versions and store a struct d3drm_texture * in struct d3drm_frame.
June 21, 2022
Re: [PATCH 2/3] d2d1: Implement effect creation for registered effect.
by Ziqing Hui
On 6/21/22 4:45 PM, Nikolay Sivov wrote:
>
>
> On 6/21/22 06:17, Ziqing Hui wrote:
>> HRESULT d2d_effect_init(struct d2d_effect *effect, struct d2d_effect_context *effect_context, const CLSID *effect_id)
>> {
>> - unsigned int i;
>> + struct d2d_effect_registration *reg;
>> + struct d2d_factory *factory;
>> + HRESULT hr;
>> effect->ID2D1Effect_iface.lpVtbl = &d2d_effect_vtbl;
>> effect->ID2D1Image_iface.lpVtbl = &d2d_effect_image_vtbl;
>> effect->refcount = 1;
>> - for (i = 0; i < ARRAY_SIZE(builtin_effects); ++i)
>> + factory = unsafe_impl_from_ID2D1Factory3((ID2D1Factory3 *)effect_context->device_context->factory);
>> + LIST_FOR_EACH_ENTRY(reg, &factory->effects, struct d2d_effect_registration, entry)
>> {
>> - if (IsEqualGUID(effect_id, &builtin_effects[i].id))
>> + if (IsEqualGUID(effect_id, ®->id))
>> {
>> - effect->min_inputs = builtin_effects[i].min_inputs;
>> - effect->max_inputs = builtin_effects[i].max_inputs;
>> - d2d_effect_SetInputCount(&effect->ID2D1Effect_iface, builtin_effects[i].default_input_count);
>> + if (FAILED(hr = reg->factory((IUnknown **)&effect->impl)))
>> + return hr;
>> + if (FAILED(hr = ID2D1EffectImpl_Initialize(effect->impl, &effect_context->ID2D1EffectContext_iface, NULL)))
>> + {
>> + ID2D1EffectImpl_Release(effect->impl);
>> + return hr;
>> + }
>> + effect->id = *effect_id;
>> + effect->min_inputs = reg->min_inputs;
>> + effect->max_inputs = reg->max_inputs;
>> + d2d_effect_SetInputCount(&effect->ID2D1Effect_iface, reg->default_input_count);
>> effect->effect_context = effect_context;
>> ID2D1EffectContext_AddRef(&effect_context->ID2D1EffectContext_iface);
>> + /* FIXME: Properties are ignored. */
>> return S_OK;
>> }
>> }
> CreateEffect() is a single place where this would be used, so I'd suggest to pick correct d2d_effect_registration there, and simply pass it to this helper.
>
> Using unsafe_* is normally reserved for externally provided pointers, that's not the case here.
>
OK, I'll do that.
>> static const struct d2d_builtin_effect_registration builtin_effects[] =
>> {
>> - {&CLSID_D2D12DAffineTransform, NULL, 1, 1, 1},
>> - {&CLSID_D2D13DPerspectiveTransform, NULL, 1, 1, 1},
>> - {&CLSID_D2D1Composite, NULL, 2, 1, 0xffffffff},
>> - {&CLSID_D2D1Crop, NULL, 1, 1, 1},
>> - {&CLSID_D2D1Shadow, NULL, 1, 1, 1},
>> - {&CLSID_D2D1Grayscale, NULL, 1, 1, 1},
>> + {&CLSID_D2D12DAffineTransform, d2d_effect_impl_create, 1, 1, 1},
>> + {&CLSID_D2D13DPerspectiveTransform, d2d_effect_impl_create, 1, 1, 1},
>> + {&CLSID_D2D1Composite, d2d_effect_impl_create, 2, 1, 0xffffffff},
>> + {&CLSID_D2D1Crop, d2d_effect_impl_create, 1, 1, 1},
>> + {&CLSID_D2D1Shadow, d2d_effect_impl_create, 1, 1, 1},
>> + {&CLSID_D2D1Grayscale, d2d_effect_impl_create, 1, 1, 1},
>> };
> I don't know how extensible this is, every _create would be different.
Yeah, each builtin effect would have a different _create. So the _create here in this patch is just a placeholder, which makes sure every builtin effect in the list can be at least successfully created for now.
My plan is something like, we take 2DAffineTransform as an example: we define a new struct for each effect:
struct d2d_2d_affine_transform
{
struct d2d_effect_impl effect_impl;
... its own fileds ...
}
d2d_effect_impl will be included in the beginning of each effect struct. The benefit of this is that we can reuse one QueryInterface, AddRef, Release, we don't have to define a new one for each new effect.
And of course, _create will be different for each effect.
June 21, 2022
Re: [PATCH 1/3] d2d1: Support registering builtin effect.
by Ziqing Hui
On 6/21/22 4:35 PM, Nikolay Sivov wrote:
>
>
> On 6/21/22 06:17, Ziqing Hui wrote:
>> @@ -616,7 +651,9 @@ struct d2d_effect
>> ID2D1Image ID2D1Image_iface;
>> LONG refcount;
>> - const struct d2d_effect_info *info;
>> + CLSID id;
>> + UINT32 min_inputs;
>> + UINT32 max_inputs;
>> struct d2d_effect_context *effect_context;
>> ID2D1Image **inputs;
> This should be a part of property system, not exposed like that.
>
>> @@ -554,21 +563,21 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_GetValue(ID2D1Effect *iface, UINT32
>> {
>> case D2D1_PROPERTY_CLSID:
>> if ((type != D2D1_PROPERTY_TYPE_UNKNOWN && type != D2D1_PROPERTY_TYPE_CLSID)
>> - || value_size != sizeof(*effect->info->clsid))
>> + || value_size != sizeof(effect->id))
>> return E_INVALIDARG;
>> - src = effect->info->clsid;
>> + src = &effect->id;
>> break;
>> case D2D1_PROPERTY_MIN_INPUTS:
>> if ((type != D2D1_PROPERTY_TYPE_UNKNOWN && type != D2D1_PROPERTY_TYPE_UINT32)
>> - || value_size != sizeof(effect->info->min_inputs))
>> + || value_size != sizeof(effect->min_inputs))
>> return E_INVALIDARG;
>> - src = &effect->info->min_inputs;
>> + src = &effect->min_inputs;
>> break;
>> case D2D1_PROPERTY_MAX_INPUTS:
>> if ((type != D2D1_PROPERTY_TYPE_UNKNOWN && type != D2D1_PROPERTY_TYPE_UINT32)
>> - || value_size != sizeof(effect->info->max_inputs))
>> + || value_size != sizeof(effect->max_inputs))
>> return E_INVALIDARG;
>> - src = &effect->info->max_inputs;
>> + src = &effect->max_inputs;
>> break;
>> default:
>> if (index < D2D1_PROPERTY_CLSID)
> Similarly, this needs rework.
>
OK, I'll rework the property system first.
>> -static const struct d2d_effect_info builtin_effects[] =
>> +struct d2d_builtin_effect_registration
>> {
>> - {&CLSID_D2D12DAffineTransform, 1, 1, 1},
>> - {&CLSID_D2D13DPerspectiveTransform, 1, 1, 1},
>> - {&CLSID_D2D1Composite, 2, 1, 0xffffffff},
>> - {&CLSID_D2D1Crop, 1, 1, 1},
>> - {&CLSID_D2D1Shadow, 1, 1, 1},
>> - {&CLSID_D2D1Grayscale, 1, 1, 1},
>> + const CLSID *id;
>> + PD2D1_EFFECT_FACTORY factory;
>> + UINT32 default_input_count;
>> + UINT32 min_inputs;
>> + UINT32 max_inputs;
>> +};
> It should be possible to reuse same structure for builtin effects.
>
Does it means that we should reuse d2d_effect_registration for the builtin effect data here? Or we keep d2d_effect_info and ignore factory field in this patch?
If use d2d_effect_registration, one problem is that CLSID is stored by itself in d2d_effect_registration, not a const pointer. So we are not able to set it statically.
Then we can have something like:
struct d2d_builtin_effects
{
const CLSID *id;
struct d2d_effect_registration reg;
}
builtin_effects[] = {....};
Does it work?
>> +HRESULT d2d_register_builtin_effects(struct d2d_factory *factory)
>> +{
>> + struct d2d_effect_registration *reg;
>> + unsigned int i;
>> +
>> + for (i = 0; i < ARRAY_SIZE(builtin_effects); ++i)
>> + {
>> + const struct d2d_builtin_effect_registration *builtin_reg = &builtin_effects[i];
>> +
>> + if (!(reg = calloc(1, sizeof(*reg))))
>> + return E_OUTOFMEMORY;
>> +
>> + reg->is_builtin = TRUE;
>> + reg->factory = builtin_reg->factory;
>> + reg->registration_count = 1;
>> + reg->id = *builtin_reg->id;
>> + reg->default_input_count = builtin_reg->default_input_count;
>> + reg->min_inputs = builtin_reg->min_inputs;
>> + reg->max_inputs = builtin_reg->max_inputs;
>> + list_add_tail(&factory->effects, ®->entry);
>> + }
>> +
>> + return S_OK;
>> +}
> I'm not sure if we want that. It should be enough to check if CLSID is for builtin in Register* call, and redirect to builtin data in CreateEffect().
>
It means that, we don't register builtin effect to factory's registered effects list, and access builtin data directly in CreateEffect()?
June 21, 2022
[PATCH 2/2] secur32: Implement SECPKG_ATTR_CIPHER_INFO.
by Hans Leidekker
From: Hans Leidekker <hans(a)codeweavers.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53180
---
dlls/secur32/schannel.c | 8 ++
dlls/secur32/schannel_gnutls.c | 222 +++++++++++++++++++++++++++++++++
dlls/secur32/secur32_priv.h | 7 ++
dlls/secur32/tests/schannel.c | 29 +++++
4 files changed, 266 insertions(+)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c
index 5b4fb196aca..7dc9bd1d21a 100644
--- a/dlls/secur32/schannel.c
+++ b/dlls/secur32/schannel.c
@@ -1244,6 +1244,12 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
struct get_application_protocol_params params = { ctx->session, protocol };
return GNUTLS_CALL( get_application_protocol, ¶ms );
}
+ case SECPKG_ATTR_CIPHER_INFO:
+ {
+ SecPkgContext_CipherInfo *info = buffer;
+ struct get_cipher_info_params params = { ctx->session, info };
+ return GNUTLS_CALL( get_cipher_info, ¶ms );
+ }
default:
FIXME("Unhandled attribute %#lx\n", attribute);
@@ -1282,6 +1288,8 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesA(
return schan_QueryContextAttributesW(context_handle, attribute, buffer);
case SECPKG_ATTR_APPLICATION_PROTOCOL:
return schan_QueryContextAttributesW(context_handle, attribute, buffer);
+ case SECPKG_ATTR_CIPHER_INFO:
+ return schan_QueryContextAttributesW(context_handle, attribute, buffer);
default:
FIXME("Unhandled attribute %#lx\n", attribute);
diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c
index ad319518a7a..39031a46086 100644
--- a/dlls/secur32/schannel_gnutls.c
+++ b/dlls/secur32/schannel_gnutls.c
@@ -698,6 +698,211 @@ static NTSTATUS schan_get_connection_info( void *args )
return SEC_E_OK;
}
+static DWORD get_protocol_version( gnutls_session_t session )
+{
+ gnutls_protocol_t proto = pgnutls_protocol_get_version( session );
+
+ switch (proto)
+ {
+ case GNUTLS_SSL3: return 0x300;
+ case GNUTLS_TLS1_0: return 0x301;
+ case GNUTLS_TLS1_1: return 0x302;
+ case GNUTLS_TLS1_2: return 0x303;
+ case GNUTLS_DTLS1_0: return 0x201;
+ case GNUTLS_DTLS1_2: return 0x202;
+ default:
+ FIXME( "unknown protocol %u\n", proto );
+ return 0;
+ }
+}
+
+static const WCHAR *get_cipher_str( gnutls_session_t session )
+{
+ static const WCHAR aesW[] = {'A','E','S',0};
+ static const WCHAR unknownW[] = {'<','u','n','k','n','o','w','n','>',0};
+ gnutls_cipher_algorithm_t cipher = pgnutls_cipher_get( session );
+
+ switch (cipher)
+ {
+ case GNUTLS_CIPHER_AES_128_CBC:
+ case GNUTLS_CIPHER_AES_192_CBC:
+ case GNUTLS_CIPHER_AES_256_CBC:
+ case GNUTLS_CIPHER_AES_128_GCM:
+ case GNUTLS_CIPHER_AES_256_GCM:
+ case GNUTLS_CIPHER_AES_128_CCM:
+ case GNUTLS_CIPHER_AES_256_CCM:
+ return aesW;
+ default:
+ FIXME( "unknown cipher %u\n", cipher );
+ return unknownW;
+ }
+}
+
+static DWORD get_cipher_len( gnutls_session_t session )
+{
+ gnutls_cipher_algorithm_t cipher = pgnutls_cipher_get( session );
+
+ switch (cipher)
+ {
+ case GNUTLS_CIPHER_AES_128_CBC:
+ case GNUTLS_CIPHER_AES_128_GCM:
+ case GNUTLS_CIPHER_AES_128_CCM:
+ return 128;
+ case GNUTLS_CIPHER_AES_192_CBC:
+ return 192;
+ case GNUTLS_CIPHER_AES_256_CBC:
+ case GNUTLS_CIPHER_AES_256_GCM:
+ case GNUTLS_CIPHER_AES_256_CCM:
+ return 256;
+ default:
+ FIXME( "unknown cipher %u\n", cipher );
+ return 0;
+ }
+}
+
+static DWORD get_cipher_block_len( gnutls_session_t session )
+{
+ gnutls_cipher_algorithm_t cipher = pgnutls_cipher_get( session );
+ return pgnutls_cipher_get_block_size( cipher );
+}
+
+static const WCHAR *get_hash_str( gnutls_session_t session, BOOL full )
+{
+ static const WCHAR shaW[] = {'S','H','A',0};
+ static const WCHAR sha1W[] = {'S','H','A','1',0};
+ static const WCHAR sha224W[] = {'S','H','A','2','2','4',0};
+ static const WCHAR sha256W[] = {'S','H','A','2','5','6',0};
+ static const WCHAR sha384W[] = {'S','H','A','3','8','4',0};
+ static const WCHAR sha512W[] = {'S','H','A','5','1','2',0};
+ static const WCHAR unknownW[] = {'<','u','n','k','n','o','w','n','>',0};
+ gnutls_mac_algorithm_t mac = pgnutls_mac_get( session );
+
+ switch (mac)
+ {
+ case GNUTLS_MAC_SHA1: return full ? sha1W : shaW;
+ case GNUTLS_MAC_SHA224: return sha224W;
+ case GNUTLS_MAC_SHA256: return sha256W;
+ case GNUTLS_MAC_SHA384: return sha384W;
+ case GNUTLS_MAC_SHA512: return sha512W;
+ default:
+ FIXME( "unknown mac %u\n", mac );
+ return unknownW;
+ }
+}
+
+static DWORD get_hash_len( gnutls_session_t session )
+{
+ gnutls_mac_algorithm_t mac = pgnutls_mac_get( session );
+ return pgnutls_mac_get_key_size( mac ) * 8;
+}
+
+static const WCHAR *get_exchange_str( gnutls_session_t session, BOOL full )
+{
+ static const WCHAR ecdhW[] = {'E','C','D','H',0};
+ static const WCHAR ecdheW[] = {'E','C','D','H','E',0};
+ static const WCHAR unknownW[] = {'<','u','n','k','n','o','w','n','>',0};
+ gnutls_kx_algorithm_t kx = pgnutls_kx_get( session );
+
+ switch (kx)
+ {
+ case GNUTLS_KX_ECDHE_RSA:
+ case GNUTLS_KX_ECDHE_ECDSA:
+ return full ? ecdheW : ecdhW;
+ default:
+ FIXME( "unknown kx %u\n", kx );
+ return unknownW;
+ }
+}
+
+static const WCHAR *get_certificate_str( gnutls_session_t session )
+{
+ static const WCHAR rsaW[] = {'R','S','A',0};
+ static const WCHAR ecdsaW[] = {'E','C','D','S','A',0};
+ static const WCHAR unknownW[] = {'<','u','n','k','n','o','w','n','>',0};
+ gnutls_kx_algorithm_t kx = pgnutls_kx_get( session );
+
+ switch (kx)
+ {
+ case GNUTLS_KX_RSA:
+ case GNUTLS_KX_RSA_EXPORT:
+ case GNUTLS_KX_DHE_RSA:
+ case GNUTLS_KX_ECDHE_RSA: return rsaW;
+ case GNUTLS_KX_ECDHE_ECDSA: return ecdsaW;
+ default:
+ FIXME( "unknown kx %u\n", kx );
+ return unknownW;
+ }
+}
+
+static const WCHAR *get_chaining_mode_str( gnutls_session_t session )
+{
+ static const WCHAR cbcW[] = {'C','B','C',0};
+ static const WCHAR ccmW[] = {'C','C','M',0};
+ static const WCHAR gcmW[] = {'G','C','M',0};
+ static const WCHAR unknownW[] = {'<','u','n','k','n','o','w','n','>',0};
+ gnutls_cipher_algorithm_t cipher = pgnutls_cipher_get( session );
+
+ switch (cipher)
+ {
+ case GNUTLS_CIPHER_AES_128_CBC:
+ case GNUTLS_CIPHER_AES_192_CBC:
+ case GNUTLS_CIPHER_AES_256_CBC:
+ return cbcW;
+ case GNUTLS_CIPHER_AES_128_GCM:
+ case GNUTLS_CIPHER_AES_256_GCM:
+ return gcmW;
+ case GNUTLS_CIPHER_AES_128_CCM:
+ case GNUTLS_CIPHER_AES_256_CCM:
+ return ccmW;
+ default:
+ FIXME( "unknown cipher %u\n", cipher );
+ return unknownW;
+ }
+}
+
+static NTSTATUS schan_get_cipher_info( void *args )
+{
+ const WCHAR tlsW[] = {'T','L','S','_',0};
+ const WCHAR underscoreW[] = {'_',0};
+ const WCHAR widthW[] = {'_','W','I','T','H','_',0};
+ const struct get_cipher_info_params *params = args;
+ gnutls_session_t session = session_from_handle( params->session );
+ SecPkgContext_CipherInfo *info = params->info;
+ char buf[11];
+ WCHAR *ptr;
+ int len;
+
+ info->dwProtocol = get_protocol_version( session );
+ info->dwCipherSuite = 0; /* FIXME */
+ info->dwBaseCipherSuite = 0; /* FIXME */
+ wcscpy( info->szCipher, get_cipher_str( session ) );
+ info->dwCipherLen = get_cipher_len( session );
+ info->dwCipherBlockLen = get_cipher_block_len( session );
+ wcscpy( info->szHash, get_hash_str( session, TRUE ) );
+ info->dwHashLen = get_hash_len( session );
+ wcscpy( info->szExchange, get_exchange_str( session, FALSE ) );
+ info->dwMinExchangeLen = 0;
+ info->dwMaxExchangeLen = 65536;
+ wcscpy( info->szCertificate, get_certificate_str( session ) );
+ info->dwKeyType = 0; /* FIXME */
+
+ wcscpy( info->szCipherSuite, tlsW );
+ wcscat( info->szCipherSuite, get_exchange_str( session, TRUE ) );
+ wcscat( info->szCipherSuite, underscoreW );
+ wcscat( info->szCipherSuite, info->szCertificate );
+ wcscat( info->szCipherSuite, widthW );
+ wcscat( info->szCipherSuite, info->szCipher );
+ wcscat( info->szCipherSuite, underscoreW );
+ len = sprintf( buf, "%u", (unsigned int)info->dwCipherLen ) + 1;
+ ptr = info->szCipherSuite + wcslen( info->szCipherSuite );
+ ntdll_umbstowcs( buf, len, ptr, len );
+ wcscat( info->szCipherSuite, underscoreW );
+ wcscat( info->szCipherSuite, get_chaining_mode_str( session ) );
+ wcscat( info->szCipherSuite, underscoreW );
+ wcscat( info->szCipherSuite, get_hash_str( session, FALSE ) );
+ return SEC_E_OK;
+}
+
static NTSTATUS schan_get_unique_channel_binding( void *args )
{
const struct get_unique_channel_binding_params *params = args;
@@ -1271,6 +1476,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
schan_dispose_session,
schan_free_certificate_credentials,
schan_get_application_protocol,
+ schan_get_cipher_info,
schan_get_connection_info,
schan_get_enabled_protocols,
schan_get_key_signature_algorithm,
@@ -1386,6 +1592,21 @@ static NTSTATUS wow64_schan_get_connection_info( void *args )
return schan_get_connection_info(¶ms);
}
+static NTSTATUS wow64_schan_get_cipher_info( void *args )
+{
+ struct
+ {
+ schan_session session;
+ PTR32 info;
+ } const *params32 = args;
+ struct get_cipher_info_params params =
+ {
+ params32->session,
+ ULongToPtr(params32->info),
+ };
+ return schan_get_connection_info(¶ms);
+}
+
static NTSTATUS wow64_schan_get_session_peer_certificate( void *args )
{
struct
@@ -1582,6 +1803,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
schan_dispose_session,
wow64_schan_free_certificate_credentials,
wow64_schan_get_application_protocol,
+ wow64_schan_get_cipher_info,
wow64_schan_get_connection_info,
schan_get_enabled_protocols,
schan_get_key_signature_algorithm,
diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h
index 5753ed47ffa..d1321b7d6fd 100644
--- a/dlls/secur32/secur32_priv.h
+++ b/dlls/secur32/secur32_priv.h
@@ -126,6 +126,12 @@ struct get_connection_info_params
SecPkgContext_ConnectionInfo *info;
};
+struct get_cipher_info_params
+{
+ schan_session session;
+ SecPkgContext_CipherInfo *info;
+};
+
struct get_session_peer_certificate_params
{
schan_session session;
@@ -206,6 +212,7 @@ enum schan_funcs
unix_dispose_session,
unix_free_certificate_credentials,
unix_get_application_protocol,
+ unix_get_cipher_info,
unix_get_connection_info,
unix_get_enabled_protocols,
unix_get_key_signature_algorithm,
diff --git a/dlls/secur32/tests/schannel.c b/dlls/secur32/tests/schannel.c
index 314b43a2607..c68474e9eae 100644
--- a/dlls/secur32/tests/schannel.c
+++ b/dlls/secur32/tests/schannel.c
@@ -1038,6 +1038,7 @@ static void test_communication(void)
CRYPT_DATA_BLOB pfx;
HCERTSTORE store;
SecPkgContext_NegotiationInfoA info;
+ SecPkgContext_CipherInfo cipher;
SecBufferDesc buffers[2];
SecBuffer *buf;
unsigned buf_size = 8192;
@@ -1291,6 +1292,34 @@ static void test_communication(void)
ok(conn_info.dwHashStrength >= 128, "conn_info.dwHashStrength = %ld\n", conn_info.dwHashStrength);
}
+ memset(&cipher, 0, sizeof(cipher));
+ cipher.dwVersion = SECPKGCONTEXT_CIPHERINFO_V1;
+ status = pQueryContextAttributesA(&context, SECPKG_ATTR_CIPHER_INFO, &cipher);
+ ok(status == SEC_E_OK || broken(status == SEC_E_UNSUPPORTED_FUNCTION) /* < vista */, "got %08lx\n", status);
+ if (status == SEC_E_OK)
+ {
+ ok(cipher.dwProtocol == 0x301, "got %lx\n", cipher.dwProtocol);
+ todo_wine ok(cipher.dwCipherSuite == 0xc014, "got %lx\n", cipher.dwCipherSuite);
+ todo_wine ok(cipher.dwBaseCipherSuite == 0xc014, "got %lx\n", cipher.dwBaseCipherSuite);
+ ok(!wcscmp(cipher.szCipherSuite, L"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA") ||
+ !wcscmp(cipher.szCipherSuite, L"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256"), /* < win10 */
+ "got %s\n", wine_dbgstr_w(cipher.szCipherSuite));
+ ok(!wcscmp(cipher.szCipher, L"AES"), "got %s\n", wine_dbgstr_w(cipher.szCipher));
+ ok(cipher.dwCipherLen == 256, "got %lu\n", cipher.dwCipherLen);
+ ok(cipher.dwCipherBlockLen == 16, "got %lu\n", cipher.dwCipherBlockLen);
+ ok(!wcscmp(cipher.szHash, L"SHA1"), "got %s\n", wine_dbgstr_w(cipher.szHash));
+ ok(cipher.dwHashLen == 160, "got %lu\n", cipher.dwHashLen);
+ ok(!wcscmp(cipher.szExchange, L"ECDH") || !wcscmp(cipher.szExchange, L"ECDH_P256"), /* < win10 */
+ "got %s\n", wine_dbgstr_w(cipher.szExchange));
+ ok(cipher.dwMinExchangeLen == 0 || cipher.dwMinExchangeLen == 256, /* < win10 */
+ "got %lu\n", cipher.dwMinExchangeLen);
+ ok(cipher.dwMaxExchangeLen == 65536 || cipher.dwMaxExchangeLen == 256, /* < win10 */
+ "got %lu\n", cipher.dwMaxExchangeLen);
+ ok(!wcscmp(cipher.szCertificate, L"RSA"), "got %s\n", wine_dbgstr_w(cipher.szCertificate));
+ todo_wine ok(cipher.dwKeyType == 0x1d || cipher.dwKeyType == 0x17, /* < win10 */
+ "got %#lx\n", cipher.dwKeyType);
+ }
+
status = pQueryContextAttributesA(&context, SECPKG_ATTR_KEY_INFO, &key_info);
ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_KEY_INFO) failed: %08lx\n", status);
if(status == SEC_E_OK) {
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/291
June 21, 2022
[PATCH 1/2] include: Move SECPKG_ATTR defines to a new header and add missing definitions.
by Hans Leidekker
From: Hans Leidekker <hans(a)codeweavers.com>
---
include/minschannel.h | 44 +++++++++++++++++++++++++++++++++++++++++++
include/schannel.h | 39 ++++++++++++++++++++++----------------
2 files changed, 67 insertions(+), 16 deletions(-)
create mode 100644 include/minschannel.h
diff --git a/include/minschannel.h b/include/minschannel.h
new file mode 100644
index 00000000000..c30ae85922b
--- /dev/null
+++ b/include/minschannel.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2022 Hans Leidekker 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
+ */
+
+#ifndef __WINE_MINSCHANNEL_H__
+#define __WINE_MINSCHANNEL_H__
+
+#define SECPKG_ATTR_ISSUER_LIST 0x50
+#define SECPKG_ATTR_REMOTE_CRED 0x51
+#define SECPKG_ATTR_LOCAL_CRED 0x52
+#define SECPKG_ATTR_REMOTE_CERT_CONTEXT 0x53
+#define SECPKG_ATTR_LOCAL_CERT_CONTEXT 0x54
+#define SECPKG_ATTR_ROOT_STORE 0x55
+#define SECPKG_ATTR_SUPPORTED_ALGS 0x56
+#define SECPKG_ATTR_CIPHER_STRENGTHS 0x57
+#define SECPKG_ATTR_SUPPORTED_PROTOCOLS 0x58
+#define SECPKG_ATTR_ISSUER_LIST_EX 0x59
+#define SECPKG_ATTR_CONNECTION_INFO 0x5a
+#define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
+#define SECPKG_ATTR_MAPPED_CRED_ATTR 0x5c
+#define SECPKG_ATTR_SESSION_INFO 0x5d
+#define SECPKG_ATTR_APP_DATA 0x5e
+#define SECPKG_ATTR_REMOTE_CERTIFICATES 0x5f
+#define SECPKG_ATTR_CLIENT_CERT_POLICY 0x60
+#define SECPKG_ATTR_CC_POLICY_RESULT 0x61
+#define SECPKG_ATTR_USE_NCRYPT 0x62
+#define SECPKG_ATTR_LOCAL_CERT_INFO 0x63
+#define SECPKG_ATTR_CIPHER_INFO 0x64
+
+#endif /* __WINE_MINSCHANNEL_H__ */
diff --git a/include/schannel.h b/include/schannel.h
index 556ec1882c9..3aa85832fd3 100644
--- a/include/schannel.h
+++ b/include/schannel.h
@@ -18,6 +18,7 @@
#ifndef __WINE_SCHANNEL_H__
#define __WINE_SCHANNEL_H__
+#include <minschannel.h>
#include <wincrypt.h>
/* Package names */
@@ -179,22 +180,6 @@ static const WCHAR SCHANNEL_NAME_W[] = { 'S','c','h','a','n','n','e','l',0 };
#define SCH_CRED_IGNORE_NO_REVOCATION_CHECK 2048
#define SCH_CRED_IGNORE_REVOCATION_OFFLINE 4096
-#define SECPKG_ATTR_ISSUER_LIST 0x50
-#define SECPKG_ATTR_REMOTE_CRED 0x51
-#define SECPKG_ATTR_LOCAL_CRED 0x52
-#define SECPKG_ATTR_REMOTE_CERT_CONTEXT 0x53
-#define SECPKG_ATTR_LOCAL_CERT_CONTEXT 0x54
-#define SECPKG_ATTR_ROOT_STORE 0x55
-#define SECPKG_ATTR_SUPPORTED_ALGS 0x56
-#define SECPKG_ATTR_CIPHER_STRENGTHS 0x57
-#define SECPKG_ATTR_SUPPORTED_PROTOCOLS 0x58
-#define SECPKG_ATTR_ISSUER_LIST_EX 0x59
-#define SECPKG_ATTR_CONNECTION_INFO 0x5a
-#define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
-#define SECPKG_ATTR_MAPPED_CRED_ATTR 0x5c
-#define SECPKG_ATTR_SESSION_INFO 0x5d
-#define SECPKG_ATTR_APP_DATA 0x5e
-
#define UNISP_RPC_ID 14
struct _HMAPPER;
@@ -299,4 +284,26 @@ typedef struct _SecPkgContext_ConnectionInfo
DWORD dwExchStrength;
} SecPkgContext_ConnectionInfo, *PSecPkgContext_ConnectionInfo;
+#define SECPKGCONTEXT_CIPHERINFO_V1 1
+#define SZ_ALG_MAX_SIZE 64
+
+typedef struct _SecPkgContext_CipherInfo
+{
+ DWORD dwVersion;
+ DWORD dwProtocol;
+ DWORD dwCipherSuite;
+ DWORD dwBaseCipherSuite;
+ WCHAR szCipherSuite[SZ_ALG_MAX_SIZE];
+ WCHAR szCipher[SZ_ALG_MAX_SIZE];
+ DWORD dwCipherLen;
+ DWORD dwCipherBlockLen;
+ WCHAR szHash[SZ_ALG_MAX_SIZE];
+ DWORD dwHashLen;
+ WCHAR szExchange[SZ_ALG_MAX_SIZE];
+ DWORD dwMinExchangeLen;
+ DWORD dwMaxExchangeLen;
+ WCHAR szCertificate[SZ_ALG_MAX_SIZE];
+ DWORD dwKeyType;
+} SecPkgContext_CipherInfo, *PSecPkgContext_CipherInfo;
+
#endif /* __WINE_SCHANNEL_H__ */
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/291
June 21, 2022
[PATCH 0/2] MR291: secur32: Implement SECPKG_ATTR_CIPHER_INFO.
by Hans Leidekker (@hans)
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/291
June 21, 2022