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
RtlFindMessage(IN PVOID BaseAddress,IN ULONG Type,IN ULONG Language,IN ULONG MessageId,OUT PMESSAGE_RESOURCE_ENTRY * MessageResourceEntry)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
RtlFormatMessageEx(IN PWSTR Message,IN ULONG MaxWidth OPTIONAL,IN BOOLEAN IgnoreInserts,IN BOOLEAN ArgumentsAreAnsi,IN BOOLEAN ArgumentsAreAnArray,IN va_list * Arguments,OUT PWSTR Buffer,IN ULONG BufferSize,OUT PULONG ReturnLength OPTIONAL,IN ULONG Flags)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
RtlFormatMessage(IN PWSTR Message,IN ULONG MaxWidth OPTIONAL,IN BOOLEAN IgnoreInserts,IN BOOLEAN ArgumentsAreAnsi,IN BOOLEAN ArgumentsAreAnArray,IN va_list * Arguments,OUT PWSTR Buffer,IN ULONG BufferSize,OUT PULONG ReturnLength OPTIONAL)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 */
200