[NTOS:KE/x64] Handle NMI vs swapgs race condition
[reactos.git] / sdk / lib / rtl / message.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/message.c
5 * PURPOSE: Message table functions
6 * PROGRAMMERS: Eric Kohl
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <rtl.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS *****************************************************************/
17
18 /*
19 * @implemented
20 */
21 NTSTATUS
22 NTAPI
23 RtlFindMessage(
24 IN PVOID BaseAddress,
25 IN ULONG Type,
26 IN ULONG Language,
27 IN ULONG MessageId,
28 OUT PMESSAGE_RESOURCE_ENTRY* MessageResourceEntry)
29 {
30 LDR_RESOURCE_INFO ResourceInfo;
31 PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
32 PMESSAGE_RESOURCE_DATA MessageTable;
33 NTSTATUS Status;
34 ULONG EntryOffset = 0, IdOffset = 0;
35 PMESSAGE_RESOURCE_ENTRY MessageEntry;
36 ULONG i;
37
38 DPRINT("RtlFindMessage()\n");
39
40 ResourceInfo.Type = Type;
41 ResourceInfo.Name = 1;
42 ResourceInfo.Language = Language;
43
44 Status = LdrFindResource_U(BaseAddress,
45 &ResourceInfo,
46 RESOURCE_DATA_LEVEL,
47 &ResourceDataEntry);
48 if (!NT_SUCCESS(Status))
49 {
50 return Status;
51 }
52
53 DPRINT("ResourceDataEntry: %p\n", ResourceDataEntry);
54
55 Status = LdrAccessResource(BaseAddress,
56 ResourceDataEntry,
57 (PVOID*)&MessageTable,
58 NULL);
59 if (!NT_SUCCESS(Status))
60 {
61 return Status;
62 }
63
64 DPRINT("MessageTable: %p\n", MessageTable);
65
66 DPRINT("NumberOfBlocks %lu\n", MessageTable->NumberOfBlocks);
67 for (i = 0; i < MessageTable->NumberOfBlocks; i++)
68 {
69 DPRINT("LoId 0x%08lx HiId 0x%08lx Offset 0x%08lx\n",
70 MessageTable->Blocks[i].LowId,
71 MessageTable->Blocks[i].HighId,
72 MessageTable->Blocks[i].OffsetToEntries);
73 }
74
75 for (i = 0; i < MessageTable->NumberOfBlocks; i++)
76 {
77 if ((MessageId >= MessageTable->Blocks[i].LowId) &&
78 (MessageId <= MessageTable->Blocks[i].HighId))
79 {
80 EntryOffset = MessageTable->Blocks[i].OffsetToEntries;
81 IdOffset = MessageId - MessageTable->Blocks[i].LowId;
82 break;
83 }
84
85 if (MessageId < MessageTable->Blocks[i].LowId)
86 {
87 return STATUS_MESSAGE_NOT_FOUND;
88 }
89 }
90
91 if (MessageTable->NumberOfBlocks <= i)
92 {
93 return STATUS_MESSAGE_NOT_FOUND;
94 }
95
96 MessageEntry = (PMESSAGE_RESOURCE_ENTRY)
97 ((PUCHAR)MessageTable + MessageTable->Blocks[i].OffsetToEntries);
98
99 DPRINT("EntryOffset 0x%08lx\n", EntryOffset);
100 DPRINT("IdOffset 0x%08lx\n", IdOffset);
101
102 DPRINT("MessageEntry: %p\n", MessageEntry);
103 for (i = 0; i < IdOffset; i++)
104 {
105 MessageEntry = (PMESSAGE_RESOURCE_ENTRY)
106 ((PUCHAR)MessageEntry + (ULONG)MessageEntry->Length);
107 }
108
109 if (MessageEntry->Flags == 0)
110 {
111 DPRINT("AnsiText: %s\n", MessageEntry->Text);
112 }
113 else
114 {
115 DPRINT("UnicodeText: %S\n", (PWSTR)MessageEntry->Text);
116 }
117
118 if (MessageResourceEntry != NULL)
119 {
120 *MessageResourceEntry = MessageEntry;
121 }
122
123 return STATUS_SUCCESS;
124 }
125
126 /*
127 * @unimplemented
128 */
129 NTSTATUS
130 NTAPI
131 RtlFormatMessageEx(
132 IN PWSTR Message,
133 IN ULONG MaxWidth OPTIONAL,
134 IN BOOLEAN IgnoreInserts,
135 IN BOOLEAN ArgumentsAreAnsi,
136 IN BOOLEAN ArgumentsAreAnArray,
137 IN va_list* Arguments,
138 OUT PWSTR Buffer,
139 IN ULONG BufferSize,
140 OUT PULONG ReturnLength OPTIONAL,
141 IN ULONG Flags)
142 {
143 DPRINT1("RtlFormatMessage(%S, %lu, %s, %s, %s, %p, %p, %lu, %p, %lx)\n",
144 Message, MaxWidth, IgnoreInserts ? "TRUE" : "FALSE", ArgumentsAreAnsi ? "TRUE" : "FALSE",
145 ArgumentsAreAnArray ? "TRUE" : "FALSE", Arguments, Buffer, BufferSize,
146 ReturnLength, Flags);
147
148 UNIMPLEMENTED;
149 return STATUS_NOT_IMPLEMENTED;
150 }
151
152 /**********************************************************************
153 * RtlFormatMessage (NTDLL.@)
154 *
155 * Formats a message (similar to sprintf).
156 *
157 * PARAMS
158 * Message [I] Message to format.
159 * MaxWidth [I] Maximum width in characters of each output line (optional).
160 * IgnoreInserts [I] Whether to copy the message without processing inserts.
161 * ArgumentsAreAnsi [I] Whether Arguments may have ANSI strings.
162 * ArgumentsAreAnArray [I] Whether Arguments is actually an array rather than a va_list *.
163 * Arguments [I]
164 * Buffer [O] Buffer to store processed message in.
165 * BufferSize [I] Size of Buffer (in bytes).
166 * ReturnLength [O] Size of the formatted message (in bytes; optional).
167 *
168 * RETURNS
169 * NTSTATUS code.
170 *
171 * @implemented
172 */
173 NTSTATUS
174 NTAPI
175 RtlFormatMessage(
176 IN PWSTR Message,
177 IN ULONG MaxWidth OPTIONAL,
178 IN BOOLEAN IgnoreInserts,
179 IN BOOLEAN ArgumentsAreAnsi,
180 IN BOOLEAN ArgumentsAreAnArray,
181 IN va_list* Arguments,
182 OUT PWSTR Buffer,
183 IN ULONG BufferSize,
184 OUT PULONG ReturnLength OPTIONAL)
185 {
186 /* Call the extended API */
187 return RtlFormatMessageEx(Message,
188 MaxWidth,
189 IgnoreInserts,
190 ArgumentsAreAnsi,
191 ArgumentsAreAnArray,
192 Arguments,
193 Buffer,
194 BufferSize,
195 ReturnLength,
196 0);
197 }
198
199 /* EOF */