Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
c944f641
Commit
c944f641
authored
Apr 06, 2022
by
Rémi Bernon
Committed by
Alexandre Julliard
Apr 06, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Support activatableClass activation context elements.
Signed-off-by:
Rémi Bernon
<
rbernon@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
c7f72cc4
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
296 additions
and
2 deletions
+296
-2
actctx.c
dlls/kernel32/tests/actctx.c
+0
-1
actctx.c
dlls/ntdll/actctx.c
+296
-1
No files found.
dlls/kernel32/tests/actctx.c
View file @
c944f641
...
...
@@ -1398,7 +1398,6 @@ static void test_find_activatable_class(HANDLE handle, const WCHAR *classid, enu
data
.
cbSize
=
sizeof
(
data
);
ret
=
FindActCtxSectionStringW
(
0
,
NULL
,
ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
,
classid
,
&
data
);
todo_wine
ok_
(
__FILE__
,
line
)(
ret
||
broken
(
!
ret
)
/* <= Win10 v1809 */
,
"FindActCtxSectionStringW failed, error %lu
\n
"
,
GetLastError
());
if
(
!
ret
)
{
...
...
dlls/ntdll/actctx.c
View file @
c944f641
...
...
@@ -301,6 +301,15 @@ struct progidredirect_data
ULONG
clsid_offset
;
};
struct
activatable_class_data
{
ULONG
size
;
DWORD
unk
;
DWORD
module_len
;
DWORD
module_offset
;
DWORD
threading_model
;
};
/*
Sections structure.
...
...
@@ -413,6 +422,25 @@ struct progidredirect_data
This sections uses generated alias guids from COM server section. This way
ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
is stored too, aligned.
- WinRT activatable class section is a plain buffer with following format:
<section header>
<module names[]>
<index[]>
<data[]> --- <class name>
<data>
Header is fixed length structure - struct strsection_header,
contains classes count;
Index is an array of fixed length index records, each record is
struct string_index.
All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
All offsets are relative to section itself.
*/
struct
progids
...
...
@@ -476,6 +504,11 @@ struct entity
WCHAR
*
value
;
WCHAR
*
ns
;
}
settings
;
struct
{
WCHAR
*
name
;
DWORD
threading_model
;
}
activatable_class
;
}
u
;
};
...
...
@@ -526,7 +559,8 @@ enum context_sections
SERVERREDIRECT_SECTION
=
8
,
IFACEREDIRECT_SECTION
=
16
,
CLRSURROGATES_SECTION
=
32
,
PROGIDREDIRECT_SECTION
=
64
PROGIDREDIRECT_SECTION
=
64
,
ACTIVATABLE_CLASS_SECTION
=
128
,
};
typedef
struct
_ACTIVATION_CONTEXT
...
...
@@ -543,6 +577,7 @@ typedef struct _ACTIVATION_CONTEXT
struct
strsection_header
*
wndclass_section
;
struct
strsection_header
*
dllredirect_section
;
struct
strsection_header
*
progid_section
;
struct
strsection_header
*
activatable_class_section
;
struct
guidsection_header
*
tlib_section
;
struct
guidsection_header
*
comserver_section
;
struct
guidsection_header
*
ifaceps_section
;
...
...
@@ -574,6 +609,7 @@ static const WCHAR current_archW[] = L"none";
static
const
WCHAR
asmv1W
[]
=
L"urn:schemas-microsoft-com:asm.v1"
;
static
const
WCHAR
asmv2W
[]
=
L"urn:schemas-microsoft-com:asm.v2"
;
static
const
WCHAR
asmv3W
[]
=
L"urn:schemas-microsoft-com:asm.v3"
;
static
const
WCHAR
winrtv1W
[]
=
L"urn:schemas-microsoft-com:winrt.v1"
;
static
const
WCHAR
compatibilityNSW
[]
=
L"urn:schemas-microsoft-com:compatibility.v1"
;
static
const
WCHAR
windowsSettings2005NSW
[]
=
L"http://schemas.microsoft.com/SMI/2005/WindowsSettings"
;
static
const
WCHAR
windowsSettings2011NSW
[]
=
L"http://schemas.microsoft.com/SMI/2011/WindowsSettings"
;
...
...
@@ -876,6 +912,9 @@ static void free_entity_array(struct entity_array *array)
RtlFreeHeap
(
GetProcessHeap
(),
0
,
entity
->
u
.
settings
.
value
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
entity
->
u
.
settings
.
ns
);
break
;
case
ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
:
RtlFreeHeap
(
GetProcessHeap
(),
0
,
entity
->
u
.
activatable_class
.
name
);
break
;
default:
FIXME
(
"Unknown entity kind %d
\n
"
,
entity
->
kind
);
}
...
...
@@ -1088,6 +1127,7 @@ static void actctx_release( ACTIVATION_CONTEXT *actctx )
RtlFreeHeap
(
GetProcessHeap
(),
0
,
actctx
->
ifaceps_section
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
actctx
->
clrsurrogate_section
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
actctx
->
progid_section
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
actctx
->
activatable_class_section
);
actctx
->
magic
=
0
;
RtlFreeHeap
(
GetProcessHeap
(),
0
,
actctx
);
}
...
...
@@ -2209,6 +2249,54 @@ static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *p
if
(
!
end
)
parse_expect_end_elem
(
xmlbuf
,
parent
);
}
static
void
parse_activatable_class_elem
(
xmlbuf_t
*
xmlbuf
,
struct
dll_redirect
*
dll
,
struct
actctx_loader
*
acl
,
const
struct
xml_elem
*
parent
)
{
struct
xml_elem
elem
;
struct
xml_attr
attr
;
BOOL
end
=
FALSE
;
struct
entity
*
entity
;
if
(
!
(
entity
=
add_entity
(
&
dll
->
entities
,
ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
)))
{
set_error
(
xmlbuf
);
return
;
}
while
(
next_xml_attr
(
xmlbuf
,
&
attr
,
&
end
))
{
if
(
xml_attr_cmp
(
&
attr
,
L"name"
))
{
if
(
!
(
entity
->
u
.
activatable_class
.
name
=
xmlstrdupW
(
&
attr
.
value
)))
set_error
(
xmlbuf
);
}
else
if
(
xml_attr_cmp
(
&
attr
,
L"threadingModel"
))
{
if
(
xmlstr_cmpi
(
&
attr
.
value
,
L"both"
))
entity
->
u
.
activatable_class
.
threading_model
=
0
;
else
if
(
xmlstr_cmpi
(
&
attr
.
value
,
L"sta"
))
entity
->
u
.
activatable_class
.
threading_model
=
1
;
else
if
(
xmlstr_cmpi
(
&
attr
.
value
,
L"mta"
))
entity
->
u
.
activatable_class
.
threading_model
=
2
;
else
set_error
(
xmlbuf
);
}
else
if
(
!
is_xmlns_attr
(
&
attr
))
{
WARN
(
"unknown attr %s
\n
"
,
debugstr_xml_attr
(
&
attr
));
}
}
acl
->
actctx
->
sections
|=
ACTIVATABLE_CLASS_SECTION
;
if
(
end
)
return
;
while
(
next_xml_elem
(
xmlbuf
,
&
elem
,
parent
))
{
WARN
(
"unknown elem %s
\n
"
,
debugstr_xml_elem
(
&
elem
));
parse_unknown_elem
(
xmlbuf
,
&
elem
);
}
}
static
void
parse_file_elem
(
xmlbuf_t
*
xmlbuf
,
struct
assembly
*
assembly
,
struct
actctx_loader
*
acl
,
const
struct
xml_elem
*
parent
)
{
...
...
@@ -2278,6 +2366,10 @@ static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
{
parse_window_class_elem
(
xmlbuf
,
dll
,
acl
,
&
elem
);
}
else
if
(
xml_elem_cmp
(
&
elem
,
L"activatableClass"
,
winrtv1W
))
{
parse_activatable_class_elem
(
xmlbuf
,
dll
,
acl
,
&
elem
);
}
else
{
WARN
(
"unknown elem %s
\n
"
,
debugstr_xml_elem
(
&
elem
));
...
...
@@ -3738,6 +3830,206 @@ static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRI
return
STATUS_SUCCESS
;
}
static
inline
struct
string_index
*
get_activatable_class_first_index
(
ACTIVATION_CONTEXT
*
actctx
)
{
return
(
struct
string_index
*
)((
BYTE
*
)
actctx
->
activatable_class_section
+
actctx
->
activatable_class_section
->
index_offset
);
}
static
inline
struct
activatable_class_data
*
get_activatable_class_data
(
ACTIVATION_CONTEXT
*
ctxt
,
struct
string_index
*
index
)
{
return
(
struct
activatable_class_data
*
)((
BYTE
*
)
ctxt
->
activatable_class_section
+
index
->
data_offset
);
}
static
NTSTATUS
build_activatable_class_section
(
ACTIVATION_CONTEXT
*
actctx
,
struct
strsection_header
**
section
)
{
unsigned
int
i
,
j
,
k
,
total_len
=
0
,
class_count
=
0
,
global_offset
=
0
,
global_len
=
0
;
struct
activatable_class_data
*
data
;
struct
strsection_header
*
header
;
struct
string_index
*
index
;
ULONG
name_offset
;
/* compute section length */
for
(
i
=
0
;
i
<
actctx
->
num_assemblies
;
i
++
)
{
struct
assembly
*
assembly
=
&
actctx
->
assemblies
[
i
];
for
(
j
=
0
;
j
<
assembly
->
num_dlls
;
j
++
)
{
struct
dll_redirect
*
dll
=
&
assembly
->
dlls
[
j
];
BOOL
has_class
=
FALSE
;
for
(
k
=
0
;
k
<
dll
->
entities
.
num
;
k
++
)
{
struct
entity
*
entity
=
&
dll
->
entities
.
base
[
k
];
if
(
entity
->
kind
==
ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
)
{
int
class_len
=
wcslen
(
entity
->
u
.
activatable_class
.
name
)
+
1
;
/* each class entry needs index, data and string data */
total_len
+=
sizeof
(
*
index
);
total_len
+=
aligned_string_len
(
class_len
*
sizeof
(
WCHAR
));
total_len
+=
sizeof
(
*
data
);
class_count
++
;
has_class
=
TRUE
;
}
}
if
(
has_class
)
{
int
module_len
=
wcslen
(
dll
->
name
)
+
1
;
global_len
+=
aligned_string_len
(
module_len
*
sizeof
(
WCHAR
));
}
}
}
total_len
+=
sizeof
(
*
header
)
+
global_len
;
header
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
total_len
);
if
(
!
header
)
return
STATUS_NO_MEMORY
;
memset
(
header
,
0
,
sizeof
(
*
header
));
header
->
magic
=
STRSECTION_MAGIC
;
header
->
size
=
sizeof
(
*
header
);
header
->
count
=
class_count
;
header
->
global_offset
=
header
->
size
;
header
->
global_len
=
global_len
;
header
->
index_offset
=
header
->
global_offset
+
header
->
global_len
;
index
=
(
struct
string_index
*
)((
BYTE
*
)
header
+
header
->
index_offset
);
name_offset
=
header
->
index_offset
+
header
->
count
*
sizeof
(
*
index
);
global_offset
=
header
->
size
;
for
(
i
=
0
;
i
<
actctx
->
num_assemblies
;
i
++
)
{
struct
assembly
*
assembly
=
&
actctx
->
assemblies
[
i
];
for
(
j
=
0
;
j
<
assembly
->
num_dlls
;
j
++
)
{
struct
dll_redirect
*
dll
=
&
assembly
->
dlls
[
j
];
int
module_len
=
wcslen
(
dll
->
name
)
*
sizeof
(
WCHAR
);
BOOL
has_class
=
FALSE
;
for
(
k
=
0
;
k
<
dll
->
entities
.
num
;
k
++
)
{
struct
entity
*
entity
=
&
dll
->
entities
.
base
[
k
];
if
(
entity
->
kind
==
ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
)
{
UNICODE_STRING
str
;
WCHAR
*
ptrW
;
/* setup new index entry */
str
.
Buffer
=
entity
->
u
.
activatable_class
.
name
;
str
.
Length
=
wcslen
(
entity
->
u
.
activatable_class
.
name
)
*
sizeof
(
WCHAR
);
str
.
MaximumLength
=
str
.
Length
+
sizeof
(
WCHAR
);
/* hash class name */
RtlHashUnicodeString
(
&
str
,
TRUE
,
HASH_STRING_ALGORITHM_X65599
,
&
index
->
hash
);
index
->
name_offset
=
name_offset
;
index
->
name_len
=
str
.
Length
;
index
->
data_offset
=
index
->
name_offset
+
aligned_string_len
(
str
.
MaximumLength
);
index
->
data_len
=
sizeof
(
*
data
);
index
->
rosterindex
=
i
+
1
;
/* class name */
ptrW
=
(
WCHAR
*
)((
BYTE
*
)
header
+
index
->
name_offset
);
memcpy
(
ptrW
,
entity
->
u
.
activatable_class
.
name
,
index
->
name_len
);
ptrW
[
index
->
name_len
/
sizeof
(
WCHAR
)]
=
0
;
/* class data */
data
=
(
struct
activatable_class_data
*
)((
BYTE
*
)
header
+
index
->
data_offset
);
data
->
size
=
sizeof
(
*
data
);
data
->
threading_model
=
entity
->
u
.
activatable_class
.
threading_model
;
data
->
module_len
=
module_len
;
data
->
module_offset
=
global_offset
;
name_offset
+=
aligned_string_len
(
str
.
MaximumLength
);
name_offset
+=
sizeof
(
*
data
);
index
++
;
has_class
=
TRUE
;
}
}
if
(
has_class
)
{
WCHAR
*
ptrW
=
(
WCHAR
*
)((
BYTE
*
)
header
+
global_offset
);
memcpy
(
ptrW
,
dll
->
name
,
module_len
);
ptrW
[
module_len
/
sizeof
(
WCHAR
)]
=
0
;
global_offset
+=
aligned_string_len
(
module_len
+
sizeof
(
WCHAR
));
}
}
}
*
section
=
header
;
return
STATUS_SUCCESS
;
}
static
NTSTATUS
find_activatable_class
(
ACTIVATION_CONTEXT
*
actctx
,
const
UNICODE_STRING
*
name
,
PACTCTX_SECTION_KEYED_DATA
data
)
{
struct
string_index
*
iter
,
*
index
=
NULL
;
struct
activatable_class_data
*
class
;
UNICODE_STRING
str
;
ULONG
hash
;
int
i
;
if
(
!
(
actctx
->
sections
&
ACTIVATABLE_CLASS_SECTION
))
return
STATUS_SXS_KEY_NOT_FOUND
;
if
(
!
actctx
->
activatable_class_section
)
{
struct
strsection_header
*
section
;
NTSTATUS
status
=
build_activatable_class_section
(
actctx
,
&
section
);
if
(
status
)
return
status
;
if
(
InterlockedCompareExchangePointer
((
void
**
)
&
actctx
->
activatable_class_section
,
section
,
NULL
))
RtlFreeHeap
(
GetProcessHeap
(),
0
,
section
);
}
hash
=
0
;
RtlHashUnicodeString
(
name
,
TRUE
,
HASH_STRING_ALGORITHM_X65599
,
&
hash
);
iter
=
get_activatable_class_first_index
(
actctx
);
for
(
i
=
0
;
i
<
actctx
->
activatable_class_section
->
count
;
i
++
)
{
if
(
iter
->
hash
==
hash
)
{
str
.
Buffer
=
(
WCHAR
*
)((
BYTE
*
)
actctx
->
activatable_class_section
+
iter
->
name_offset
);
str
.
Length
=
iter
->
name_len
;
if
(
RtlEqualUnicodeString
(
&
str
,
name
,
TRUE
))
{
index
=
iter
;
break
;
}
else
WARN
(
"hash collision 0x%08x, %s, %s
\n
"
,
hash
,
debugstr_us
(
name
),
debugstr_us
(
&
str
));
}
iter
++
;
}
if
(
!
index
)
return
STATUS_SXS_KEY_NOT_FOUND
;
if
(
data
)
{
class
=
get_activatable_class_data
(
actctx
,
index
);
data
->
ulDataFormatVersion
=
1
;
data
->
lpData
=
class
;
/* full length includes string length with nulls */
data
->
ulLength
=
class
->
size
+
class
->
module_len
+
sizeof
(
WCHAR
);
data
->
lpSectionGlobalData
=
(
BYTE
*
)
actctx
->
activatable_class_section
+
actctx
->
activatable_class_section
->
global_offset
;
data
->
ulSectionGlobalDataLength
=
actctx
->
activatable_class_section
->
global_len
;
data
->
lpSectionBase
=
actctx
->
activatable_class_section
;
data
->
ulSectionTotalLength
=
RtlSizeHeap
(
GetProcessHeap
(),
0
,
actctx
->
activatable_class_section
);
data
->
hActCtx
=
NULL
;
if
(
data
->
cbSize
>=
FIELD_OFFSET
(
ACTCTX_SECTION_KEYED_DATA
,
ulAssemblyRosterIndex
)
+
sizeof
(
ULONG
))
data
->
ulAssemblyRosterIndex
=
index
->
rosterindex
;
}
return
STATUS_SUCCESS
;
}
static
NTSTATUS
build_tlib_section
(
ACTIVATION_CONTEXT
*
actctx
,
struct
guidsection_header
**
section
)
{
unsigned
int
i
,
j
,
k
,
total_len
=
0
,
tlib_count
=
0
,
names_len
=
0
;
...
...
@@ -4813,6 +5105,9 @@ static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
case
ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
FIXME
(
"Unsupported yet section_kind %x
\n
"
,
section_kind
);
return
STATUS_SXS_SECTION_NOT_FOUND
;
case
ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
:
status
=
find_activatable_class
(
actctx
,
section_name
,
data
);
break
;
default:
WARN
(
"Unknown section_kind %x
\n
"
,
section_kind
);
return
STATUS_SXS_SECTION_NOT_FOUND
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment