Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-fonts
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
Aleksandr Isakov
wine-fonts
Commits
32298b1d
Commit
32298b1d
authored
Jul 14, 2022
by
Dmitry Timoshkov
Committed by
Vitaly Lipatov
Jul 30, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Add support for loading MUI resources. (eterbug #15663)
Signed-off-by:
Dmitry Timoshkov
<
dmitry@baikal.ru
>
Signed-off-by:
Nurlan Usenov
<
suren@etersoft.ru
>
parent
d06edb96
Pipeline
#8877
failed
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
306 additions
and
30 deletions
+306
-30
loader.c
dlls/ntdll/loader.c
+2
-0
ntdll_misc.h
dlls/ntdll/ntdll_misc.h
+1
-0
resource.c
dlls/ntdll/resource.c
+303
-30
No files found.
dlls/ntdll/loader.c
View file @
32298b1d
...
...
@@ -4004,6 +4004,8 @@ NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
MODULE_FlushModrefs
();
}
unload_MUI_module
(
hModule
);
TRACE
(
"END
\n
"
);
}
else
...
...
dlls/ntdll/ntdll_misc.h
View file @
32298b1d
...
...
@@ -81,6 +81,7 @@ extern void RELAY_SetupDLL( HMODULE hmod ) DECLSPEC_HIDDEN;
extern
void
SNOOP_SetupDLL
(
HMODULE
hmod
)
DECLSPEC_HIDDEN
;
extern
const
WCHAR
windows_dir
[]
DECLSPEC_HIDDEN
;
extern
const
WCHAR
system_dir
[]
DECLSPEC_HIDDEN
;
extern
void
unload_MUI_module
(
HMODULE
)
DECLSPEC_HIDDEN
;
extern
void
(
FASTCALL
*
pBaseThreadInitThunk
)(
DWORD
,
LPTHREAD_START_ROUTINE
,
void
*
)
DECLSPEC_HIDDEN
;
extern
const
struct
unix_funcs
*
unix_funcs
DECLSPEC_HIDDEN
;
...
...
dlls/ntdll/resource.c
View file @
32298b1d
...
...
@@ -283,34 +283,6 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH LdrFindResourceDirectory_U( HMODULE hmod, cons
}
/**********************************************************************
* LdrFindResource_U (NTDLL.@)
*/
NTSTATUS
WINAPI
DECLSPEC_HOTPATCH
LdrFindResource_U
(
HMODULE
hmod
,
const
LDR_RESOURCE_INFO
*
info
,
ULONG
level
,
const
IMAGE_RESOURCE_DATA_ENTRY
**
entry
)
{
const
void
*
res
;
NTSTATUS
status
;
__TRY
{
if
(
info
)
TRACE
(
"module %p type %s name %s lang %04x level %d
\n
"
,
hmod
,
debugstr_w
((
LPCWSTR
)
info
->
Type
),
level
>
1
?
debugstr_w
((
LPCWSTR
)
info
->
Name
)
:
""
,
level
>
2
?
info
->
Language
:
0
,
level
);
status
=
find_entry
(
hmod
,
info
,
level
,
&
res
,
FALSE
);
if
(
status
==
STATUS_SUCCESS
)
*
entry
=
res
;
}
__EXCEPT_PAGE_FAULT
{
return
GetExceptionCode
();
}
__ENDTRY
;
return
status
;
}
/* don't penalize other platforms with stuff needed on i386 for compatibility */
#ifdef __i386__
NTSTATUS
WINAPI
DECLSPEC_HIDDEN
access_resource
(
HMODULE
hmod
,
const
IMAGE_RESOURCE_DATA_ENTRY
*
entry
,
...
...
@@ -351,6 +323,14 @@ static inline NTSTATUS access_resource( HMODULE hmod, const IMAGE_RESOURCE_DATA_
return
status
;
}
static
BOOL
map_MUI_module
(
HMODULE
*
hmod
);
NTSTATUS
WINAPI
DECLSPEC_HIDDEN
access_MUI_resource
(
HMODULE
hmod
,
const
IMAGE_RESOURCE_DATA_ENTRY
*
entry
,
void
**
ptr
,
ULONG
*
size
)
{
map_MUI_module
(
&
hmod
);
return
access_resource
(
hmod
,
entry
,
ptr
,
size
);
}
/**********************************************************************
* LdrAccessResource (NTDLL.@)
*
...
...
@@ -368,7 +348,7 @@ __ASM_STDCALL_FUNC( LdrAccessResource, 16,
"pushl 16(%ebp)
\n\t
"
"pushl 12(%ebp)
\n\t
"
"pushl 8(%ebp)
\n\t
"
"call "
__ASM_STDCALL
(
"access_resource"
,
16
)
"
\n\t
"
"call "
__ASM_STDCALL
(
"access_
MUI_
resource"
,
16
)
"
\n\t
"
"leave
\n\t
"
"ret $16"
)
...
...
@@ -376,7 +356,7 @@ __ASM_STDCALL_FUNC( LdrAccessResource, 16,
NTSTATUS
WINAPI
LdrAccessResource
(
HMODULE
hmod
,
const
IMAGE_RESOURCE_DATA_ENTRY
*
entry
,
void
**
ptr
,
ULONG
*
size
)
{
return
access_resource
(
hmod
,
entry
,
ptr
,
size
);
return
access_
MUI_
resource
(
hmod
,
entry
,
ptr
,
size
);
}
#endif
...
...
@@ -420,3 +400,296 @@ NTSTATUS WINAPI RtlFindMessage( HMODULE hmod, ULONG type, ULONG lang,
}
return
STATUS_MESSAGE_NOT_FOUND
;
}
/* MUI resource cache */
static
int
MUI_cache_count
,
MUI_cache_size
;
struct
MUI_cache_entry
{
HMODULE
hmod
;
HMODULE
hmod_MUI
;
};
static
struct
MUI_cache_entry
*
MUI_cache
;
static
RTL_CRITICAL_SECTION
MUI_cache_section
;
static
RTL_CRITICAL_SECTION_DEBUG
MUI_cache_section_debug
=
{
0
,
0
,
&
MUI_cache_section
,
{
&
MUI_cache_section_debug
.
ProcessLocksList
,
&
MUI_cache_section_debug
.
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": MUI_cache_section"
)
}
};
static
RTL_CRITICAL_SECTION
MUI_cache_section
=
{
&
MUI_cache_section_debug
,
-
1
,
0
,
0
,
0
,
0
};
typedef
struct
_MUI_RC_CONFIG
{
DWORD
dwSignature
;
DWORD
dwSize
;
DWORD
dwVersion
;
DWORD
unknown1
[
3
];
DWORD
dwFileType
;
BYTE
pServiceChecksum
[
16
];
BYTE
pChecksum
[
16
];
DWORD
unknown2
[
6
];
DWORD
dwTypeNameMainOffset
;
DWORD
dwTypeNameMainSize
;
DWORD
dwTypeIDMainOffset
;
DWORD
dwTypeIDMainSize
;
DWORD
dwTypeNameMUIOffset
;
DWORD
dwTypeNameMUISize
;
DWORD
dwTypeIDMUIOffset
;
DWORD
dwTypeIDMUISize
;
DWORD
unknown3
[
2
];
DWORD
dwLanguageNameOffset
;
DWORD
dwLanguageNameSize
;
}
MUI_RC_CONFIG
;
static
BOOL
map_MUI_module
(
HMODULE
*
hmod
)
{
BOOL
ret
=
FALSE
;
RtlEnterCriticalSection
(
&
MUI_cache_section
);
if
(
MUI_cache_count
)
{
int
min
=
0
,
max
=
MUI_cache_count
-
1
;
while
(
min
<=
max
)
{
int
pos
=
(
min
+
max
)
/
2
;
if
((
ULONG_PTR
)
*
hmod
>
(
ULONG_PTR
)
MUI_cache
[
pos
].
hmod
)
min
=
pos
+
1
;
else
if
((
ULONG_PTR
)
*
hmod
<
(
ULONG_PTR
)
MUI_cache
[
pos
].
hmod
)
max
=
pos
-
1
;
else
{
TRACE
(
"found hmod %p => %p in MUI cache
\n
"
,
*
hmod
,
MUI_cache
[
pos
].
hmod_MUI
);
*
hmod
=
MUI_cache
[
pos
].
hmod_MUI
;
ret
=
TRUE
;
break
;
}
}
}
RtlLeaveCriticalSection
(
&
MUI_cache_section
);
return
ret
;
}
static
void
add_MUI_module
(
HMODULE
hmod
,
HMODULE
hmod_MUI
)
{
int
pos
=
0
;
RtlEnterCriticalSection
(
&
MUI_cache_section
);
if
(
MUI_cache_count
)
{
int
min
=
0
,
max
=
MUI_cache_count
-
1
;
while
(
min
<=
max
)
{
pos
=
(
min
+
max
)
/
2
;
if
((
ULONG_PTR
)
hmod
>
(
ULONG_PTR
)
MUI_cache
[
pos
].
hmod
)
min
=
pos
+
1
;
else
if
((
ULONG_PTR
)
hmod
<
(
ULONG_PTR
)
MUI_cache
[
pos
].
hmod
)
max
=
pos
-
1
;
else
{
TRACE
(
"hmod %p already in MUI cache
\n
"
,
hmod
);
RtlLeaveCriticalSection
(
&
MUI_cache_section
);
return
;
}
}
pos
=
min
;
}
TRACE
(
"adding %p => %p at pos %d
\n
"
,
hmod
,
hmod_MUI
,
pos
);
if
(
MUI_cache_count
==
MUI_cache_size
)
{
struct
MUI_cache_entry
*
new_MUI_cache
;
int
new_MUI_cache_size
;
if
(
!
MUI_cache_size
)
{
new_MUI_cache_size
=
16
;
new_MUI_cache
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
sizeof
(
*
MUI_cache
)
*
new_MUI_cache_size
);
}
else
{
new_MUI_cache_size
=
MUI_cache_size
*
2
;
new_MUI_cache
=
RtlReAllocateHeap
(
GetProcessHeap
(),
0
,
MUI_cache
,
sizeof
(
*
MUI_cache
)
*
new_MUI_cache_size
);
}
if
(
!
new_MUI_cache
)
{
RtlLeaveCriticalSection
(
&
MUI_cache_section
);
return
;
}
MUI_cache
=
new_MUI_cache
;
MUI_cache_size
=
new_MUI_cache_size
;
}
memmove
(
&
MUI_cache
[
pos
+
1
],
&
MUI_cache
[
pos
],
sizeof
(
*
MUI_cache
)
*
(
MUI_cache_count
-
pos
));
MUI_cache
[
pos
].
hmod
=
hmod
;
MUI_cache
[
pos
].
hmod_MUI
=
hmod_MUI
;
MUI_cache_count
++
;
RtlLeaveCriticalSection
(
&
MUI_cache_section
);
}
void
unload_MUI_module
(
HMODULE
hmod
)
{
RtlEnterCriticalSection
(
&
MUI_cache_section
);
if
(
MUI_cache_count
)
{
int
min
=
0
,
max
=
MUI_cache_count
-
1
;
while
(
min
<=
max
)
{
int
pos
=
(
min
+
max
)
/
2
;
if
((
ULONG_PTR
)
hmod
>
(
ULONG_PTR
)
MUI_cache
[
pos
].
hmod
)
min
=
pos
+
1
;
else
if
((
ULONG_PTR
)
hmod
<
(
ULONG_PTR
)
MUI_cache
[
pos
].
hmod
)
max
=
pos
-
1
;
else
{
TRACE
(
"found hmod %p => %p in MUI cache
\n
"
,
hmod
,
MUI_cache
[
pos
].
hmod_MUI
);
NtUnmapViewOfSection
(
NtCurrentProcess
(),
MUI_cache
[
pos
].
hmod_MUI
);
MUI_cache_count
--
;
memmove
(
&
MUI_cache
[
pos
],
&
MUI_cache
[
pos
+
1
],
sizeof
(
*
MUI_cache
)
*
(
MUI_cache_count
-
pos
));
break
;
}
}
}
RtlLeaveCriticalSection
(
&
MUI_cache_section
);
}
static
NTSTATUS
load_MUI_module
(
HMODULE
*
hmod
,
BOOL
*
is_MUI
)
{
const
void
*
res
=
NULL
;
MUI_RC_CONFIG
*
mui
;
LDR_RESOURCE_INFO
mui_rsrc
;
NTSTATUS
status
;
*
is_MUI
=
FALSE
;
mui_rsrc
.
Type
=
(
ULONG_PTR
)
L"MUI"
;
mui_rsrc
.
Name
=
1
;
mui_rsrc
.
Language
=
MAKELANGID
(
LANG_NEUTRAL
,
SUBLANG_NEUTRAL
);
if
((
status
=
find_entry
(
*
hmod
,
&
mui_rsrc
,
3
,
&
res
,
FALSE
))
==
STATUS_SUCCESS
)
{
if
(
!
access_resource
(
*
hmod
,
res
,
(
void
**
)
&
mui
,
NULL
))
{
const
WCHAR
*
lang
=
(
const
WCHAR
*
)((
const
BYTE
*
)
mui
+
mui
->
dwLanguageNameOffset
);
char
buf
[
MAX_PATH
*
sizeof
(
WCHAR
)
+
sizeof
(
UNICODE_STRING
)];
MEMORY_SECTION_NAME
*
name
=
(
MEMORY_SECTION_NAME
*
)
buf
;
OBJECT_ATTRIBUTES
attr
;
HANDLE
file
,
mapping
;
IO_STATUS_BLOCK
io
;
SIZE_T
size
;
WCHAR
*
p
,
*
file_part
;
HMODULE
hmod_MUI
;
*
is_MUI
=
TRUE
;
if
(
mui
->
dwSignature
!=
0xfecdfecd
)
return
STATUS_MUI_INVALID_RC_CONFIG
;
status
=
NtQueryVirtualMemory
(
NtCurrentProcess
(),
*
hmod
,
MemoryMappedFilenameInformation
,
name
,
sizeof
(
buf
),
NULL
);
if
(
status
)
{
ERR
(
"NtQueryVirtualMemory(%p) => %08lx
\n
"
,
*
hmod
,
status
);
return
status
;
}
p
=
wcsrchr
(
name
->
SectionFileName
.
Buffer
,
'\\'
);
if
(
!
p
)
p
=
name
->
SectionFileName
.
Buffer
;
file_part
=
p
+
wcslen
(
lang
)
+
1
;
memmove
(
file_part
,
p
,
(
wcslen
(
p
)
+
1
)
*
sizeof
(
WCHAR
)
);
wcscpy
(
p
+
1
,
lang
);
file_part
[
0
]
=
'\\'
;
wcscat
(
p
,
L".mui"
);
name
->
SectionFileName
.
Length
=
wcslen
(
name
->
SectionFileName
.
Buffer
)
*
sizeof
(
WCHAR
);
name
->
SectionFileName
.
MaximumLength
=
name
->
SectionFileName
.
Length
+
sizeof
(
WCHAR
);
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
Attributes
=
OBJ_CASE_INSENSITIVE
;
attr
.
ObjectName
=
&
name
->
SectionFileName
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
status
=
NtOpenFile
(
&
file
,
GENERIC_READ
|
SYNCHRONIZE
,
&
attr
,
&
io
,
FILE_SHARE_READ
,
FILE_SYNCHRONOUS_IO_NONALERT
|
FILE_NON_DIRECTORY_FILE
);
if
(
status
)
{
ERR
(
"NtOpenFile(%s) => %08lx
\n
"
,
debugstr_us
(
&
name
->
SectionFileName
),
status
);
return
status
;
}
status
=
NtCreateSection
(
&
mapping
,
STANDARD_RIGHTS_REQUIRED
|
SECTION_QUERY
|
SECTION_MAP_READ
,
NULL
,
NULL
,
PAGE_READONLY
,
SEC_IMAGE
,
file
);
NtClose
(
file
);
if
(
status
)
{
ERR
(
"NtCreateSection => %08lx
\n
"
,
status
);
return
status
;
}
hmod_MUI
=
NULL
;
size
=
0
;
status
=
NtMapViewOfSection
(
mapping
,
NtCurrentProcess
(),
(
void
**
)
&
hmod_MUI
,
0
,
0
,
NULL
,
&
size
,
ViewShare
,
0
,
PAGE_READONLY
);
NtClose
(
mapping
);
if
(
status
==
STATUS_IMAGE_NOT_AT_BASE
)
status
=
STATUS_SUCCESS
;
if
(
status
)
{
ERR
(
"NtMapViewOfSection => %08lx
\n
"
,
status
);
return
status
;
}
add_MUI_module
(
*
hmod
,
hmod_MUI
);
*
hmod
=
hmod_MUI
;
}
}
return
status
;
}
/**********************************************************************
* LdrFindResource_U (NTDLL.@)
*/
NTSTATUS
WINAPI
DECLSPEC_HOTPATCH
LdrFindResource_U
(
HMODULE
hmod
,
const
LDR_RESOURCE_INFO
*
info
,
ULONG
level
,
const
IMAGE_RESOURCE_DATA_ENTRY
**
entry
)
{
const
void
*
res
;
NTSTATUS
status
;
__TRY
{
if
(
info
)
TRACE
(
"module %p type %s name %s lang %04x level %d
\n
"
,
hmod
,
debugstr_w
((
LPCWSTR
)
info
->
Type
),
level
>
1
?
debugstr_w
((
LPCWSTR
)
info
->
Name
)
:
""
,
level
>
2
?
info
->
Language
:
0
,
level
);
status
=
find_entry
(
hmod
,
info
,
level
,
&
res
,
FALSE
);
if
(
status
==
STATUS_SUCCESS
)
*
entry
=
res
;
else
{
BOOL
is_MUI
;
status
=
load_MUI_module
(
&
hmod
,
&
is_MUI
);
if
(
status
==
STATUS_SUCCESS
)
{
status
=
find_entry
(
hmod
,
info
,
level
,
&
res
,
FALSE
);
if
(
status
==
STATUS_SUCCESS
)
*
entry
=
res
;
}
else
if
(
is_MUI
)
ERR
(
"module %p has MUI_RC_CONFIG but .mui resource file was not found
\n
"
,
hmod
);
}
}
__EXCEPT_PAGE_FAULT
{
return
GetExceptionCode
();
}
__ENDTRY
;
return
status
;
}
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