summaryrefslogtreecommitdiffstats
path: root/private/ntos/rtl/message.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/rtl/message.c')
-rw-r--r--private/ntos/rtl/message.c460
1 files changed, 460 insertions, 0 deletions
diff --git a/private/ntos/rtl/message.c b/private/ntos/rtl/message.c
new file mode 100644
index 000000000..825fc95c6
--- /dev/null
+++ b/private/ntos/rtl/message.c
@@ -0,0 +1,460 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ message.c
+
+Abstract:
+
+ Message table resource accessing functions
+
+Author:
+
+ Steve Wood (stevewo) 10-Sep-1991
+
+Revision History:
+
+--*/
+
+#include "ntrtlp.h"
+#include "string.h"
+#include "stdio.h"
+
+#if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
+#pragma alloc_text(PAGE,RtlFindMessage)
+#endif
+
+NTSTATUS
+RtlFindMessage(
+ IN PVOID DllHandle,
+ IN ULONG MessageTableId,
+ IN ULONG MessageLanguageId,
+ IN ULONG MessageId,
+ OUT PMESSAGE_RESOURCE_ENTRY *MessageEntry
+ )
+{
+ NTSTATUS Status;
+ ULONG NumberOfBlocks;
+ ULONG EntryIndex;
+ PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
+ PMESSAGE_RESOURCE_DATA MessageData;
+ PMESSAGE_RESOURCE_BLOCK MessageBlock;
+ PCHAR s;
+ ULONG ResourceIdPath[ 3 ];
+
+ RTL_PAGED_CODE();
+
+ ResourceIdPath[ 0 ] = MessageTableId;
+ ResourceIdPath[ 1 ] = 1;
+ ResourceIdPath[ 2 ] = MessageLanguageId;
+
+ Status = LdrpSearchResourceSection_U( DllHandle,
+ ResourceIdPath,
+ 3,
+ FALSE,
+ (PVOID *)&ResourceDataEntry
+ );
+ if (!NT_SUCCESS( Status )) {
+ return( Status );
+ }
+
+ Status = LdrpAccessResourceData( DllHandle,
+ ResourceDataEntry,
+ (PVOID *)&MessageData,
+ NULL
+ );
+ if (!NT_SUCCESS( Status )) {
+ return( Status );
+ }
+
+ NumberOfBlocks = MessageData->NumberOfBlocks;
+ MessageBlock = &MessageData->Blocks[ 0 ];
+ while (NumberOfBlocks--) {
+ if (MessageId >= MessageBlock->LowId &&
+ MessageId <= MessageBlock->HighId
+ ) {
+ s = (PCHAR)MessageData + MessageBlock->OffsetToEntries;
+ EntryIndex = MessageId - MessageBlock->LowId;
+ while (EntryIndex--) {
+ s += ((PMESSAGE_RESOURCE_ENTRY)s)->Length;
+ }
+
+ *MessageEntry = (PMESSAGE_RESOURCE_ENTRY)s;
+ return( STATUS_SUCCESS );
+ }
+
+ MessageBlock++;
+ }
+
+ return( STATUS_MESSAGE_NOT_FOUND );
+}
+
+#ifndef NTOS_KERNEL_RUNTIME
+
+#define MAX_INSERTS 200
+
+NTSTATUS
+RtlFormatMessage(
+ IN PWSTR MessageFormat,
+ IN ULONG MaximumWidth OPTIONAL,
+ IN BOOLEAN IgnoreInserts,
+ IN BOOLEAN ArgumentsAreAnsi,
+ IN BOOLEAN ArgumentsAreAnArray,
+ IN va_list *Arguments,
+ OUT PWSTR Buffer,
+ IN ULONG Length,
+ OUT PULONG ReturnLength OPTIONAL
+ )
+{
+ ULONG Column;
+ int cchRemaining, cchWritten;
+ PULONG ArgumentsArray = (PULONG)Arguments;
+ ULONG rgInserts[ MAX_INSERTS ], cSpaces;
+ ULONG MaxInsert, CurInsert;
+ ULONG PrintParameterCount;
+ ULONG PrintParameter1;
+ ULONG PrintParameter2;
+ WCHAR PrintFormatString[ 32 ];
+ BOOLEAN DefaultedFormatString;
+ WCHAR c;
+ PWSTR s, s1;
+ PWSTR lpDst, lpDstBeg, lpDstLastSpace;
+
+ cchRemaining = Length / sizeof( WCHAR );
+ lpDst = Buffer;
+ MaxInsert = 0;
+ lpDstLastSpace = NULL;
+ Column = 0;
+ s = MessageFormat;
+ while (*s != UNICODE_NULL) {
+ if (*s == L'%') {
+ s++;
+ lpDstBeg = lpDst;
+ if (*s >= L'1' && *s <= L'9') {
+ CurInsert = *s++ - L'0';
+ if (*s >= L'0' && *s <= L'9') {
+ CurInsert = (CurInsert * 10) + (*s++ - L'0');
+ if (*s >= L'0' && *s <= L'9') {
+ CurInsert = (CurInsert * 10) + (*s++ - L'0');
+ if (*s >= L'0' && *s <= L'9') {
+ return( STATUS_INVALID_PARAMETER );
+ }
+ }
+ }
+ CurInsert -= 1;
+
+ PrintParameterCount = 0;
+ if (*s == L'!') {
+ DefaultedFormatString = FALSE;
+ s1 = PrintFormatString;
+ *s1++ = L'%';
+ s++;
+ while (*s != L'!') {
+ if (*s != UNICODE_NULL) {
+ if (s1 >= &PrintFormatString[ 31 ]) {
+ return( STATUS_INVALID_PARAMETER );
+ }
+
+ if (*s == L'*') {
+ if (PrintParameterCount++ > 1) {
+ return( STATUS_INVALID_PARAMETER );
+ }
+ }
+
+ *s1++ = *s++;
+ }
+ else {
+ return( STATUS_INVALID_PARAMETER );
+ }
+ }
+
+ s++;
+ *s1 = UNICODE_NULL;
+ }
+ else {
+ DefaultedFormatString = TRUE;
+ wcscpy( PrintFormatString, L"%s" );
+ s1 = PrintFormatString + wcslen( PrintFormatString );
+ }
+
+ if (IgnoreInserts) {
+ if (!wcscmp( PrintFormatString, L"%s" )) {
+ cchWritten = _snwprintf( lpDst,
+ cchRemaining,
+ L"%%%u",
+ CurInsert+1
+ );
+ }
+ else {
+ cchWritten = _snwprintf( lpDst,
+ cchRemaining,
+ L"%%%u!%s!",
+ CurInsert+1,
+ &PrintFormatString[ 1 ]
+ );
+ }
+ }
+ else
+ if (ARGUMENT_PRESENT( Arguments )) {
+ if ((CurInsert+PrintParameterCount) >= MAX_INSERTS) {
+ return( STATUS_INVALID_PARAMETER );
+ }
+
+ if (ArgumentsAreAnsi) {
+ if (s1[ -1 ] == L'c' && s1[ -2 ] != L'h'
+ && s1[ -2 ] != L'w' && s1[ -2 ] != L'l') {
+ wcscpy( &s1[ -1 ], L"hc" );
+ }
+ else
+ if (s1[ -1 ] == L's' && s1[ -2 ] != L'h'
+ && s1[ -2 ] != L'w' && s1[ -2 ] != L'l') {
+ wcscpy( &s1[ -1 ], L"hs" );
+ }
+ else if (s1[ -1 ] == L'S') {
+ s1[ -1 ] = L's';
+ }
+ else if (s1[ -1 ] == L'C') {
+ s1[ -1 ] = L'c';
+ }
+ }
+
+ while (CurInsert >= MaxInsert) {
+ if (ArgumentsAreAnArray) {
+ rgInserts[ MaxInsert++ ] = *((PULONG)Arguments)++;
+ }
+ else {
+ rgInserts[ MaxInsert++ ] = va_arg(*Arguments, ULONG);
+ }
+ }
+
+ s1 = (PWSTR)rgInserts[ CurInsert ];
+ PrintParameter1 = 0;
+ PrintParameter2 = 0;
+ if (PrintParameterCount > 0) {
+ if (ArgumentsAreAnArray) {
+ PrintParameter1 = rgInserts[ MaxInsert++ ] = *((PULONG)Arguments)++;
+ }
+ else {
+ PrintParameter1 = rgInserts[ MaxInsert++ ] = va_arg( *Arguments, ULONG );
+ }
+
+ if (PrintParameterCount > 1) {
+ if (ArgumentsAreAnArray) {
+ PrintParameter2 = rgInserts[ MaxInsert++ ] = *((PULONG)Arguments)++;
+ }
+ else {
+ PrintParameter2 = rgInserts[ MaxInsert++ ] = va_arg( *Arguments, ULONG );
+ }
+ }
+ }
+
+ cchWritten = _snwprintf( lpDst,
+ cchRemaining,
+ PrintFormatString,
+ s1,
+ PrintParameter1,
+ PrintParameter2
+ );
+ }
+ else {
+ return( STATUS_INVALID_PARAMETER );
+ }
+
+ if ((cchRemaining -= cchWritten) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ lpDst += cchWritten;
+ }
+ else
+ if (*s == L'0') {
+ break;
+ }
+ else
+ if (!*s) {
+ return( STATUS_INVALID_PARAMETER );
+ }
+ else
+ if (*s == L'r') {
+ if ((cchRemaining -= 1) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ *lpDst++ = L'\r';
+ s++;
+ lpDstBeg = NULL;
+ }
+ else
+ if (*s == L'n') {
+ if ((cchRemaining -= 2) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ *lpDst++ = L'\r';
+ *lpDst++ = L'\n';
+ s++;
+ lpDstBeg = NULL;
+ }
+ else
+ if (*s == L't') {
+ if ((cchRemaining -= 1) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ if (Column % 8) {
+ Column = (Column + 7) & ~7;
+ }
+ else {
+ Column += 8;
+ }
+
+ lpDstLastSpace = lpDst;
+ *lpDst++ = L'\t';
+ s++;
+ }
+ else
+ if (*s == L'b') {
+ if ((cchRemaining -= 1) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ lpDstLastSpace = lpDst;
+ *lpDst++ = L' ';
+ s++;
+ }
+ else
+ if (IgnoreInserts) {
+ if ((cchRemaining -= 2) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ *lpDst++ = L'%';
+ *lpDst++ = *s++;
+ }
+ else {
+ if ((cchRemaining -= 1) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ *lpDst++ = *s++;
+ }
+
+ if (lpDstBeg == NULL) {
+ lpDstLastSpace = NULL;
+ Column = 0;
+ }
+ else {
+ Column += lpDst - lpDstBeg;
+ }
+ }
+ else {
+ c = *s++;
+ if (c == L'\r' || c == L'\n') {
+ if ((c == L'\n' && *s == L'\r') ||
+ (c == L'\r' && *s == L'\n')
+ ) {
+ s++;
+ }
+
+ if (MaximumWidth != 0) {
+ lpDstLastSpace = lpDst;
+ c = L' ';
+ }
+ else {
+ c = L'\n';
+ }
+ }
+
+
+ if (c == L'\n') {
+ if ((cchRemaining -= 2) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ *lpDst++ = L'\r';
+ *lpDst++ = L'\n';
+ lpDstLastSpace = NULL;
+ Column = 0;
+ }
+ else {
+ if ((cchRemaining -= 1) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ if (c == L' ') {
+ lpDstLastSpace = lpDst;
+ }
+
+ *lpDst++ = c;
+ Column += 1;
+ }
+ }
+
+ if (MaximumWidth != 0 &&
+ MaximumWidth != 0xFFFFFFFF &&
+ Column >= MaximumWidth
+ ) {
+ if (lpDstLastSpace != NULL) {
+ lpDstBeg = lpDstLastSpace;
+ while (*lpDstBeg == L' ' || *lpDstBeg == L'\t') {
+ lpDstBeg += 1;
+ if (lpDstBeg == lpDst) {
+ break;
+ }
+ }
+ while (lpDstLastSpace > Buffer) {
+ if (lpDstLastSpace[ -1 ] == L' ' || lpDstLastSpace[ -1 ] == L'\t') {
+ lpDstLastSpace -= 1;
+ }
+ else {
+ break;
+ }
+ }
+
+ cSpaces = lpDstBeg - lpDstLastSpace;
+ if (cSpaces == 1) {
+ if ((cchRemaining -= 1) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ }
+ else
+ if (cSpaces > 2) {
+ cchRemaining += (cSpaces - 2);
+ }
+
+ memmove( lpDstLastSpace + 2,
+ lpDstBeg,
+ (lpDst - lpDstBeg) * sizeof( WCHAR )
+ );
+ *lpDstLastSpace++ = L'\r';
+ *lpDstLastSpace++ = L'\n';
+ Column = lpDst - lpDstBeg;
+ lpDst = lpDstLastSpace + Column;
+ lpDstLastSpace = NULL;
+ }
+ else {
+ if ((cchRemaining -= 2) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ *lpDst++ = L'\r';
+ *lpDst++ = L'\n';
+ lpDstLastSpace = NULL;
+ Column = 0;
+ }
+ }
+ }
+
+ if ((cchRemaining -= 1) <= 0) {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ *lpDst++ = '\0';
+ if ( ARGUMENT_PRESENT(ReturnLength) ) {
+ *ReturnLength = (lpDst - Buffer) * sizeof( WCHAR );
+ }
+ return( STATUS_SUCCESS );
+}
+#endif