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
5bb9f86d
Commit
5bb9f86d
authored
May 13, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Implement RtlFormatMessage().
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
b3a0a393
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
252 additions
and
31 deletions
+252
-31
ntdll.spec
dlls/ntdll/ntdll.spec
+2
-1
ntdll_misc.h
dlls/ntdll/ntdll_misc.h
+1
-0
resource.c
dlls/ntdll/resource.c
+0
-28
rtlstr.c
dlls/ntdll/rtlstr.c
+245
-0
ntoskrnl.exe.spec
dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+2
-1
winternl.h
include/winternl.h
+2
-1
No files found.
dlls/ntdll/ntdll.spec
View file @
5bb9f86d
...
...
@@ -667,7 +667,8 @@
@ stub RtlFlushPropertySet
# @ stub RtlFlushSecureMemoryCache
@ stdcall RtlFormatCurrentUserKeyPath(ptr)
@ stdcall RtlFormatMessage(ptr long long long long ptr ptr long)
@ stdcall RtlFormatMessage(ptr long long long long ptr ptr long ptr)
@ stdcall RtlFormatMessageEx(ptr long long long long ptr ptr long ptr long)
@ stdcall RtlFreeAnsiString(ptr)
@ stdcall RtlFreeHandle(ptr ptr)
@ stdcall RtlFreeHeap(long long ptr)
...
...
dlls/ntdll/ntdll_misc.h
View file @
5bb9f86d
...
...
@@ -325,6 +325,7 @@ LPWSTR __cdecl NTDLL_wcstok( LPWSTR str, LPCWSTR delim );
LONG
__cdecl
NTDLL_wcstol
(
LPCWSTR
s
,
LPWSTR
*
end
,
INT
base
);
ULONG
__cdecl
NTDLL_wcstoul
(
LPCWSTR
s
,
LPWSTR
*
end
,
INT
base
);
int
WINAPIV
NTDLL_swprintf
(
WCHAR
*
str
,
const
WCHAR
*
format
,
...
);
int
WINAPIV
_snwprintf_s
(
WCHAR
*
str
,
SIZE_T
size
,
SIZE_T
len
,
const
WCHAR
*
format
,
...
);
#define wcsicmp(s1,s2) NTDLL__wcsicmp(s1,s2)
#define wcsnicmp(s1,s2,n) NTDLL__wcsnicmp(s1,s2,n)
...
...
dlls/ntdll/resource.c
View file @
5bb9f86d
...
...
@@ -419,31 +419,3 @@ NTSTATUS WINAPI RtlFindMessage( HMODULE hmod, ULONG type, ULONG lang,
}
return
STATUS_MESSAGE_NOT_FOUND
;
}
/**********************************************************************
* RtlFormatMessage (NTDLL.@)
*
* Formats a message (similar to sprintf).
*
* PARAMS
* Message [I] Message to format.
* MaxWidth [I] Maximum width in characters of each output line.
* IgnoreInserts [I] Whether to copy the message without processing inserts.
* Ansi [I] Whether Arguments may have ANSI strings.
* ArgumentsIsArray [I] Whether Arguments is actually an array rather than a va_list *.
* Buffer [O] Buffer to store processed message in.
* BufferSize [I] Size of Buffer (in bytes?).
*
* RETURNS
* NTSTATUS code.
*/
NTSTATUS
WINAPI
RtlFormatMessage
(
LPWSTR
Message
,
UCHAR
MaxWidth
,
BOOLEAN
IgnoreInserts
,
BOOLEAN
Ansi
,
BOOLEAN
ArgumentIsArray
,
__ms_va_list
*
Arguments
,
LPWSTR
Buffer
,
ULONG
BufferSize
)
{
FIXME
(
"(%s, %u, %s, %s, %s, %p, %p, %d)
\n
"
,
debugstr_w
(
Message
),
MaxWidth
,
IgnoreInserts
?
"TRUE"
:
"FALSE"
,
Ansi
?
"TRUE"
:
"FALSE"
,
ArgumentIsArray
?
"TRUE"
:
"FALSE"
,
Arguments
,
Buffer
,
BufferSize
);
return
STATUS_SUCCESS
;
}
dlls/ntdll/rtlstr.c
View file @
5bb9f86d
...
...
@@ -1707,3 +1707,248 @@ NTSTATUS WINAPI RtlStringFromGUID(const GUID* guid, UNICODE_STRING *str)
return
STATUS_SUCCESS
;
}
/***********************************************************************
* Message formatting
***********************************************************************/
struct
format_message_args
{
int
last
;
/* last used arg */
ULONG_PTR
*
array
;
/* args array */
__ms_va_list
*
list
;
/* args va_list */
UINT64
arglist
[
102
];
/* arguments fetched from va_list */
};
static
NTSTATUS
add_chars
(
WCHAR
**
buffer
,
WCHAR
*
end
,
const
WCHAR
*
str
,
ULONG
len
)
{
if
(
len
>
end
-
*
buffer
)
return
STATUS_BUFFER_OVERFLOW
;
memcpy
(
*
buffer
,
str
,
len
*
sizeof
(
WCHAR
)
);
*
buffer
+=
len
;
return
STATUS_SUCCESS
;
}
static
UINT64
get_arg
(
int
nr
,
struct
format_message_args
*
args_data
,
BOOL
is64
)
{
if
(
nr
==
-
1
)
nr
=
args_data
->
last
+
1
;
while
(
nr
>
args_data
->
last
)
args_data
->
arglist
[
args_data
->
last
++
]
=
is64
?
va_arg
(
*
args_data
->
list
,
UINT64
)
:
va_arg
(
*
args_data
->
list
,
ULONG_PTR
);
return
args_data
->
arglist
[
nr
-
1
];
}
static
NTSTATUS
add_format
(
WCHAR
**
buffer
,
WCHAR
*
end
,
const
WCHAR
**
src
,
int
insert
,
BOOLEAN
ansi
,
struct
format_message_args
*
args_data
)
{
static
const
WCHAR
modifiers
[]
=
{
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
' '
,
'+'
,
'-'
,
'*'
,
'#'
,
'.'
,
0
};
const
WCHAR
*
format
=
*
src
;
WCHAR
*
p
,
fmt
[
32
];
ULONG_PTR
args
[
5
]
=
{
0
};
BOOL
is_64
=
FALSE
;
UINT64
val
;
int
len
,
stars
=
0
,
nb_args
=
0
;
p
=
fmt
;
*
p
++
=
'%'
;
if
(
*
format
++
==
'!'
)
{
const
WCHAR
*
end
=
wcschr
(
format
,
'!'
);
if
(
!
end
||
end
-
format
>
ARRAY_SIZE
(
fmt
)
-
2
)
return
STATUS_INVALID_PARAMETER
;
*
src
=
end
+
1
;
while
(
wcschr
(
modifiers
,
*
format
))
{
if
(
*
format
==
'*'
)
stars
++
;
*
p
++
=
*
format
++
;
}
if
(
stars
>
2
)
return
STATUS_INVALID_PARAMETER
;
switch
(
*
format
)
{
case
'c'
:
case
'C'
:
case
's'
:
case
'S'
:
if
(
ansi
)
*
p
++
=
*
format
++
^
(
's'
-
'S'
);
break
;
case
'I'
:
if
(
sizeof
(
void
*
)
==
sizeof
(
int
)
&&
format
[
1
]
==
'6'
&&
format
[
2
]
==
'4'
)
is_64
=
TRUE
;
break
;
}
while
(
format
!=
end
)
*
p
++
=
*
format
++
;
}
else
*
p
++
=
ansi
?
'S'
:
's'
;
/* simple string */
*
p
=
0
;
if
(
args_data
->
list
)
{
get_arg
(
insert
-
1
,
args_data
,
is_64
);
/* make sure previous args have been fetched */
while
(
stars
--
)
{
args
[
nb_args
++
]
=
get_arg
(
insert
,
args_data
,
FALSE
);
insert
=
-
1
;
}
/* replicate MS bug: drop an argument when using va_list with width/precision */
if
(
insert
==
-
1
)
args_data
->
last
--
;
val
=
get_arg
(
insert
,
args_data
,
is_64
);
args
[
nb_args
++
]
=
val
;
args
[
nb_args
]
=
val
>>
32
;
}
else
if
(
args_data
->
array
)
{
args
[
nb_args
++
]
=
args_data
->
array
[
insert
-
1
];
if
(
args_data
->
last
<
insert
)
args_data
->
last
=
insert
;
/* replicate MS bug: first arg is considered 64-bit, even if it's actually width or precision */
if
(
is_64
)
nb_args
++
;
while
(
stars
--
)
args
[
nb_args
++
]
=
args_data
->
array
[
args_data
->
last
++
];
}
else
return
STATUS_INVALID_PARAMETER
;
len
=
_snwprintf_s
(
*
buffer
,
end
-
*
buffer
,
end
-
*
buffer
-
1
,
fmt
,
args
[
0
],
args
[
1
],
args
[
2
],
args
[
3
],
args
[
4
]
);
if
(
len
==
-
1
)
return
STATUS_BUFFER_OVERFLOW
;
*
buffer
+=
len
;
return
STATUS_SUCCESS
;
}
/**********************************************************************
* RtlFormatMessage (NTDLL.@)
*/
NTSTATUS
WINAPI
RtlFormatMessage
(
const
WCHAR
*
src
,
ULONG
width
,
BOOLEAN
ignore_inserts
,
BOOLEAN
ansi
,
BOOLEAN
is_array
,
__ms_va_list
*
args
,
WCHAR
*
buffer
,
ULONG
size
,
ULONG
*
retsize
)
{
return
RtlFormatMessageEx
(
src
,
width
,
ignore_inserts
,
ansi
,
is_array
,
args
,
buffer
,
size
,
retsize
,
0
);
}
/**********************************************************************
* RtlFormatMessageEx (NTDLL.@)
*/
NTSTATUS
WINAPI
RtlFormatMessageEx
(
const
WCHAR
*
src
,
ULONG
width
,
BOOLEAN
ignore_inserts
,
BOOLEAN
ansi
,
BOOLEAN
is_array
,
__ms_va_list
*
args
,
WCHAR
*
buffer
,
ULONG
size
,
ULONG
*
retsize
,
ULONG
flags
)
{
static
const
WCHAR
emptyW
=
0
;
static
const
WCHAR
spaceW
=
' '
;
static
const
WCHAR
crW
=
'\r'
;
static
const
WCHAR
tabW
=
'\t'
;
static
const
WCHAR
crlfW
[]
=
{
'\r'
,
'\n'
};
struct
format_message_args
args_data
;
NTSTATUS
status
=
STATUS_SUCCESS
;
WCHAR
*
start
=
buffer
;
/* start of buffer */
WCHAR
*
end
=
buffer
+
size
/
sizeof
(
WCHAR
);
/* end of buffer */
WCHAR
*
line
=
buffer
;
/* start of last line */
WCHAR
*
space
=
NULL
;
/* last space */
if
(
flags
)
FIXME
(
"%s unknown flags %x
\n
"
,
debugstr_w
(
src
),
flags
);
args_data
.
last
=
0
;
args_data
.
array
=
is_array
?
(
ULONG_PTR
*
)
args
:
NULL
;
args_data
.
list
=
is_array
?
NULL
:
args
;
for
(
;
*
src
;
src
++
)
{
switch
(
*
src
)
{
case
'\r'
:
if
(
src
[
1
]
==
'\n'
)
src
++
;
/* fall through */
case
'\n'
:
if
(
!
width
)
{
status
=
add_chars
(
&
buffer
,
end
,
crlfW
,
2
);
line
=
buffer
;
space
=
NULL
;
break
;
}
/* fall through */
case
' '
:
space
=
buffer
;
status
=
add_chars
(
&
buffer
,
end
,
&
spaceW
,
1
);
break
;
case
'\t'
:
if
(
space
==
buffer
-
1
)
space
=
buffer
;
status
=
add_chars
(
&
buffer
,
end
,
&
tabW
,
1
);
break
;
case
'%'
:
src
++
;
switch
(
*
src
)
{
case
0
:
return
STATUS_INVALID_PARAMETER
;
case
't'
:
if
(
!
width
)
{
status
=
add_chars
(
&
buffer
,
end
,
&
tabW
,
1
);
break
;
}
/* fall through */
case
'n'
:
status
=
add_chars
(
&
buffer
,
end
,
crlfW
,
2
);
line
=
buffer
;
space
=
NULL
;
break
;
case
'r'
:
status
=
add_chars
(
&
buffer
,
end
,
&
crW
,
1
);
line
=
buffer
;
space
=
NULL
;
break
;
case
'0'
:
while
(
src
[
1
])
src
++
;
break
;
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
if
(
!
ignore_inserts
)
{
int
nr
=
*
src
++
-
'0'
;
if
(
*
src
>=
'0'
&&
*
src
<=
'9'
)
nr
=
nr
*
10
+
*
src
++
-
'0'
;
status
=
add_format
(
&
buffer
,
end
,
&
src
,
nr
,
ansi
,
&
args_data
);
src
--
;
break
;
}
/* fall through */
default:
if
(
ignore_inserts
)
status
=
add_chars
(
&
buffer
,
end
,
src
-
1
,
2
);
else
status
=
add_chars
(
&
buffer
,
end
,
src
,
1
);
break
;
}
break
;
default:
status
=
add_chars
(
&
buffer
,
end
,
src
,
1
);
break
;
}
if
(
status
)
return
status
;
if
(
width
&&
buffer
-
line
>=
width
)
{
LONG_PTR
diff
=
2
;
WCHAR
*
next
;
if
(
space
)
/* split line at the last space */
{
next
=
space
+
1
;
while
(
space
>
line
&&
(
space
[
-
1
]
==
' '
||
space
[
-
1
]
==
'\t'
))
space
--
;
diff
-=
next
-
space
;
}
else
space
=
next
=
buffer
;
/* split at the end of the buffer */
if
(
diff
>
0
&&
end
-
buffer
<
diff
)
return
STATUS_BUFFER_OVERFLOW
;
memmove
(
space
+
2
,
next
,
(
buffer
-
next
)
*
sizeof
(
WCHAR
)
);
buffer
+=
diff
;
memcpy
(
space
,
crlfW
,
sizeof
(
crlfW
)
);
line
=
space
+
2
;
space
=
NULL
;
}
}
if
((
status
=
add_chars
(
&
buffer
,
end
,
&
emptyW
,
1
)))
return
status
;
*
retsize
=
(
buffer
-
start
)
*
sizeof
(
WCHAR
);
return
STATUS_SUCCESS
;
}
dlls/ntoskrnl.exe/ntoskrnl.exe.spec
View file @
5bb9f86d
...
...
@@ -1069,7 +1069,8 @@
@ stub RtlFindUnicodePrefix
@ stdcall RtlFirstFreeAce(ptr ptr)
@ stdcall RtlFormatCurrentUserKeyPath(ptr)
@ stdcall RtlFormatMessage(ptr long long long long ptr ptr long)
@ stdcall RtlFormatMessage(ptr long long long long ptr ptr long ptr)
@ stdcall RtlFormatMessageEx(ptr long long long long ptr ptr long ptr long)
@ stdcall RtlFreeAnsiString(ptr)
@ stdcall RtlFreeHeap(long long ptr)
@ stdcall RtlFreeOemString(ptr)
...
...
include/winternl.h
View file @
5bb9f86d
...
...
@@ -2841,7 +2841,8 @@ NTSYSAPI ULONG WINAPI RtlFindSetBitsAndClear(PRTL_BITMAP,ULONG,ULONG);
NTSYSAPI
ULONG
WINAPI
RtlFindSetRuns
(
PCRTL_BITMAP
,
PRTL_BITMAP_RUN
,
ULONG
,
BOOLEAN
);
NTSYSAPI
BOOLEAN
WINAPI
RtlFirstFreeAce
(
PACL
,
PACE_HEADER
*
);
NTSYSAPI
NTSTATUS
WINAPI
RtlFormatCurrentUserKeyPath
(
PUNICODE_STRING
);
NTSYSAPI
NTSTATUS
WINAPI
RtlFormatMessage
(
LPWSTR
,
UCHAR
,
BOOLEAN
,
BOOLEAN
,
BOOLEAN
,
__ms_va_list
*
,
LPWSTR
,
ULONG
);
NTSYSAPI
NTSTATUS
WINAPI
RtlFormatMessage
(
LPCWSTR
,
ULONG
,
BOOLEAN
,
BOOLEAN
,
BOOLEAN
,
__ms_va_list
*
,
LPWSTR
,
ULONG
,
ULONG
*
);
NTSYSAPI
NTSTATUS
WINAPI
RtlFormatMessageEx
(
LPCWSTR
,
ULONG
,
BOOLEAN
,
BOOLEAN
,
BOOLEAN
,
__ms_va_list
*
,
LPWSTR
,
ULONG
,
ULONG
*
,
ULONG
);
NTSYSAPI
void
WINAPI
RtlFreeAnsiString
(
PANSI_STRING
);
NTSYSAPI
BOOLEAN
WINAPI
RtlFreeHandle
(
RTL_HANDLE_TABLE
*
,
RTL_HANDLE
*
);
NTSYSAPI
BOOLEAN
WINAPI
RtlFreeHeap
(
HANDLE
,
ULONG
,
PVOID
);
...
...
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