Commit 74877137 authored by Magnus Hagander's avatar Magnus Hagander

Write to the Windows eventlog in UTF16, converting the message encoding

as necessary.

Itagaki Takahiro with some changes from me
parent 76c09dbe
......@@ -42,7 +42,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.217 2009/07/03 19:14:25 petere Exp $
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.218 2009/10/17 00:24:50 mha Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -111,8 +111,10 @@ static int syslog_facility = LOG_LOCAL0;
static void write_syslog(int level, const char *line);
#endif
static void write_console(const char *line, int len);
#ifdef WIN32
static void write_eventlog(int level, const char *line);
static void write_eventlog(int level, const char *line, int len);
#endif
/* We provide a small stack of ErrorData records for re-entrant cases */
......@@ -1567,10 +1569,11 @@ write_syslog(int level, const char *line)
* Write a message line to the windows event log
*/
static void
write_eventlog(int level, const char *line)
write_eventlog(int level, const char *line, int len)
{
int eventlevel = EVENTLOG_ERROR_TYPE;
static HANDLE evtHandle = INVALID_HANDLE_VALUE;
WCHAR *utf16;
int eventlevel = EVENTLOG_ERROR_TYPE;
static HANDLE evtHandle = INVALID_HANDLE_VALUE;
if (evtHandle == INVALID_HANDLE_VALUE)
{
......@@ -1606,8 +1609,34 @@ write_eventlog(int level, const char *line)
break;
}
ReportEvent(evtHandle,
/*
* Convert message to UTF16 text and write it with ReportEventW,
* but fall-back into ReportEventA if conversion failed.
*
* Also verify that we are not on our way into error recursion trouble
* due to error messages thrown deep inside pgwin32_toUTF16().
*/
if (GetDatabaseEncoding() != GetPlatformEncoding() &&
!in_error_recursion_trouble())
{
utf16 = pgwin32_toUTF16(line, len, NULL);
if (utf16)
{
ReportEventW(evtHandle,
eventlevel,
0,
0, /* All events are Id 0 */
NULL,
1,
0,
(LPCWSTR *) &utf16,
NULL);
pfree(utf16);
return;
}
}
ReportEventA(evtHandle,
eventlevel,
0,
0, /* All events are Id 0 */
......@@ -1619,6 +1648,52 @@ write_eventlog(int level, const char *line)
}
#endif /* WIN32 */
static void
write_console(const char *line, int len)
{
#ifdef WIN32
/*
* WriteConsoleW() will fail of stdout is redirected, so just fall through
* to writing unconverted to the logfile in this case.
*/
if (GetDatabaseEncoding() != GetPlatformEncoding() &&
!in_error_recursion_trouble() &&
!redirection_done)
{
WCHAR *utf16;
int utf16len;
utf16 = pgwin32_toUTF16(line, len, &utf16len);
if (utf16 != NULL)
{
HANDLE stdHandle;
DWORD written;
stdHandle = GetStdHandle(STD_ERROR_HANDLE);
if (WriteConsoleW(stdHandle, utf16, utf16len, &written, NULL))
{
pfree(utf16);
return;
}
/*
* In case WriteConsoleW() failed, fall back to writing the message
* unconverted.
*/
pfree(utf16);
}
}
#else
/*
* Conversion on non-win32 platform is not implemented yet.
* It requires non-throw version of pg_do_encoding_conversion(),
* that converts unconvertable characters to '?' without errors.
*/
#endif
write(fileno(stderr), line, len);
}
/*
* setup formatted_log_time, for consistent times between CSV and regular logs
*/
......@@ -2206,7 +2281,7 @@ send_message_to_server_log(ErrorData *edata)
/* Write to eventlog, if enabled */
if (Log_destination & LOG_DESTINATION_EVENTLOG)
{
write_eventlog(edata->elevel, buf.data);
write_eventlog(edata->elevel, buf.data, buf.len);
}
#endif /* WIN32 */
......@@ -2230,10 +2305,10 @@ send_message_to_server_log(ErrorData *edata)
* because that's really a pipe to the syslogger process.
*/
else if (pgwin32_is_service())
write_eventlog(edata->elevel, buf.data);
write_eventlog(edata->elevel, buf.data, buf.len);
#endif
else
write(fileno(stderr), buf.data, buf.len);
write_console(buf.data, buf.len);
}
/* If in the syslogger process, try to write messages direct to file */
......@@ -2256,12 +2331,12 @@ send_message_to_server_log(ErrorData *edata)
{
const char *msg = _("Not safe to send CSV data\n");
write(fileno(stderr), msg, strlen(msg));
write_console(msg, strlen(msg));
if (!(Log_destination & LOG_DESTINATION_STDERR) &&
whereToSendOutput != DestDebug)
{
/* write message to stderr unless we just sent it above */
write(fileno(stderr), buf.data, buf.len);
write_console(buf.data, buf.len);
}
pfree(buf.data);
}
......@@ -2642,6 +2717,9 @@ void
write_stderr(const char *fmt,...)
{
va_list ap;
#ifdef WIN32
char errbuf[2048]; /* Arbitrary size? */
#endif
fmt = _(fmt);
......@@ -2651,6 +2729,7 @@ write_stderr(const char *fmt,...)
vfprintf(stderr, fmt, ap);
fflush(stderr);
#else
vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
/*
* On Win32, we print to stderr if running on a console, or write to
......@@ -2658,16 +2737,12 @@ write_stderr(const char *fmt,...)
*/
if (pgwin32_is_service()) /* Running as a service */
{
char errbuf[2048]; /* Arbitrary size? */
vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
write_eventlog(ERROR, errbuf);
write_eventlog(ERROR, errbuf, strlen(errbuf));
}
else
{
/* Not running as service, write to stderr */
vfprintf(stderr, fmt, ap);
write_console(errbuf, strlen(errbuf));
fflush(stderr);
}
#endif
......
......@@ -2,7 +2,7 @@
* Encoding names and routines for work with it. All
* in this file is shared bedween FE and BE.
*
* $PostgreSQL: pgsql/src/backend/utils/mb/encnames.c,v 1.39 2009/04/24 08:43:50 mha Exp $
* $PostgreSQL: pgsql/src/backend/utils/mb/encnames.c,v 1.40 2009/10/17 00:24:51 mha Exp $
*/
#ifdef FRONTEND
#include "postgres_fe.h"
......@@ -300,134 +300,55 @@ sizeof(pg_encname_tbl) / sizeof(pg_encname_tbl[0]) - 1;
* XXX must be sorted by the same order as enum pg_enc (in mb/pg_wchar.h)
* ----------
*/
#ifndef WIN32
#define DEF_ENC2NAME(name, codepage) { #name, PG_##name }
#else
#define DEF_ENC2NAME(name, codepage) { #name, PG_##name, codepage }
#endif
pg_enc2name pg_enc2name_tbl[] =
{
{
"SQL_ASCII", PG_SQL_ASCII
},
{
"EUC_JP", PG_EUC_JP
},
{
"EUC_CN", PG_EUC_CN
},
{
"EUC_KR", PG_EUC_KR
},
{
"EUC_TW", PG_EUC_TW
},
{
"EUC_JIS_2004", PG_EUC_JIS_2004
},
{
"UTF8", PG_UTF8
},
{
"MULE_INTERNAL", PG_MULE_INTERNAL
},
{
"LATIN1", PG_LATIN1
},
{
"LATIN2", PG_LATIN2
},
{
"LATIN3", PG_LATIN3
},
{
"LATIN4", PG_LATIN4
},
{
"LATIN5", PG_LATIN5
},
{
"LATIN6", PG_LATIN6
},
{
"LATIN7", PG_LATIN7
},
{
"LATIN8", PG_LATIN8
},
{
"LATIN9", PG_LATIN9
},
{
"LATIN10", PG_LATIN10
},
{
"WIN1256", PG_WIN1256
},
{
"WIN1258", PG_WIN1258
},
{
"WIN866", PG_WIN866
},
{
"WIN874", PG_WIN874
},
{
"KOI8R", PG_KOI8R
},
{
"WIN1251", PG_WIN1251
},
{
"WIN1252", PG_WIN1252
},
{
"ISO_8859_5", PG_ISO_8859_5
},
{
"ISO_8859_6", PG_ISO_8859_6
},
{
"ISO_8859_7", PG_ISO_8859_7
},
{
"ISO_8859_8", PG_ISO_8859_8
},
{
"WIN1250", PG_WIN1250
},
{
"WIN1253", PG_WIN1253
},
{
"WIN1254", PG_WIN1254
},
{
"WIN1255", PG_WIN1255
},
{
"WIN1257", PG_WIN1257
},
{
"KOI8U", PG_KOI8U
},
{
"SJIS", PG_SJIS
},
{
"BIG5", PG_BIG5
},
{
"GBK", PG_GBK
},
{
"UHC", PG_UHC
},
{
"GB18030", PG_GB18030
},
{
"JOHAB", PG_JOHAB
},
{
"SHIFT_JIS_2004", PG_SHIFT_JIS_2004
}
DEF_ENC2NAME(SQL_ASCII, 0),
DEF_ENC2NAME(EUC_JP, 20932),
DEF_ENC2NAME(EUC_CN, 20936),
DEF_ENC2NAME(EUC_KR, 51949),
DEF_ENC2NAME(EUC_TW, 0),
DEF_ENC2NAME(EUC_JIS_2004, 20932),
DEF_ENC2NAME(UTF8, 65001),
DEF_ENC2NAME(MULE_INTERNAL, 0),
DEF_ENC2NAME(LATIN1, 28591),
DEF_ENC2NAME(LATIN2, 28592),
DEF_ENC2NAME(LATIN3, 28593),
DEF_ENC2NAME(LATIN4, 28594),
DEF_ENC2NAME(LATIN5, 28599),
DEF_ENC2NAME(LATIN6, 0),
DEF_ENC2NAME(LATIN7, 0),
DEF_ENC2NAME(LATIN8, 0),
DEF_ENC2NAME(LATIN9, 28605),
DEF_ENC2NAME(LATIN10, 0),
DEF_ENC2NAME(WIN1256, 1256),
DEF_ENC2NAME(WIN1258, 1258),
DEF_ENC2NAME(WIN866, 866),
DEF_ENC2NAME(WIN874, 874),
DEF_ENC2NAME(KOI8R, 20866),
DEF_ENC2NAME(WIN1251, 1251),
DEF_ENC2NAME(WIN1252, 1252),
DEF_ENC2NAME(ISO_8859_5, 28595),
DEF_ENC2NAME(ISO_8859_6, 28596),
DEF_ENC2NAME(ISO_8859_7, 28597),
DEF_ENC2NAME(ISO_8859_8, 28598),
DEF_ENC2NAME(WIN1250, 1250),
DEF_ENC2NAME(WIN1253, 1253),
DEF_ENC2NAME(WIN1254, 1254),
DEF_ENC2NAME(WIN1255, 1255),
DEF_ENC2NAME(WIN1257, 1257),
DEF_ENC2NAME(KOI8U, 21866),
DEF_ENC2NAME(SJIS, 932),
DEF_ENC2NAME(BIG5, 950),
DEF_ENC2NAME(GBK, 936),
DEF_ENC2NAME(UHC, 0),
DEF_ENC2NAME(GB18030, 54936),
DEF_ENC2NAME(JOHAB, 0),
DEF_ENC2NAME(SHIFT_JIS_2004, 932)
};
/* ----------
......
......@@ -4,7 +4,7 @@
*
* Tatsuo Ishii
*
* $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.89 2009/07/07 19:28:56 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.90 2009/10/17 00:24:51 mha Exp $
*/
#include "postgres.h"
......@@ -58,6 +58,7 @@ static FmgrInfo *ToClientConvProc = NULL;
*/
static pg_enc2name *ClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
static pg_enc2name *DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
static pg_enc2name *PlatformEncoding = NULL;
/*
* During backend startup we can't set client encoding because we (a)
......@@ -978,3 +979,66 @@ pg_client_encoding(PG_FUNCTION_ARGS)
Assert(ClientEncoding);
return DirectFunctionCall1(namein, CStringGetDatum(ClientEncoding->name));
}
int
GetPlatformEncoding(void)
{
if (PlatformEncoding == NULL)
PlatformEncoding = &pg_enc2name_tbl[pg_get_encoding_from_locale("")];
return PlatformEncoding->encoding;
}
#ifdef WIN32
/*
* Result is palloc'ed null-terminated utf16 string. The character length
* is also passed to utf16len if not null. Returns NULL iff failed.
*/
WCHAR *
pgwin32_toUTF16(const char *str, int len, int *utf16len)
{
WCHAR *utf16;
int dstlen;
UINT codepage;
codepage = pg_enc2name_tbl[GetDatabaseEncoding()].codepage;
/*
* Use MultiByteToWideChar directly if there is a corresponding codepage,
* or double conversion through UTF8 if not.
*/
if (codepage != 0)
{
utf16 = (WCHAR *) palloc(sizeof(WCHAR) * (len + 1));
dstlen = MultiByteToWideChar(codepage, 0, str, len, utf16, len);
utf16[dstlen] = L'\0';
}
else
{
char *utf8;
utf8 = (char *) pg_do_encoding_conversion((unsigned char *) str,
len, GetDatabaseEncoding(), PG_UTF8);
if (utf8 != str)
len = strlen(utf8);
utf16 = (WCHAR *) palloc(sizeof(WCHAR) * (len + 1));
dstlen = MultiByteToWideChar(CP_UTF8, 0, utf8, len, utf16, len);
utf16[dstlen] = L'\0';
if (utf8 != str)
pfree(utf8);
}
if (dstlen == 0 && len > 0)
{
pfree(utf16);
return NULL; /* error */
}
if (utf16len)
*utf16len = len;
return utf16;
}
#endif
......@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/mb/pg_wchar.h,v 1.91 2009/06/11 14:49:11 momjian Exp $
* $PostgreSQL: pgsql/src/include/mb/pg_wchar.h,v 1.92 2009/10/17 00:24:51 mha Exp $
*
* NOTES
* This is used both by the backend and by libpq, but should not be
......@@ -257,6 +257,9 @@ typedef struct pg_enc2name
{
char *name;
pg_enc encoding;
#ifdef WIN32
unsigned codepage; /* codepage for WIN32 */
#endif
} pg_enc2name;
extern pg_enc2name pg_enc2name_tbl[];
......@@ -402,6 +405,7 @@ extern const char *pg_get_client_encoding_name(void);
extern void SetDatabaseEncoding(int encoding);
extern int GetDatabaseEncoding(void);
extern const char *GetDatabaseEncodingName(void);
extern int GetPlatformEncoding(void);
extern void pg_bind_textdomain_codeset(const char *domainname);
extern int pg_valid_client_encoding(const char *name);
......@@ -458,4 +462,8 @@ extern void mic2latin_with_table(const unsigned char *mic, unsigned char *p,
extern bool pg_utf8_islegal(const unsigned char *source, int length);
#ifdef WIN32
extern WCHAR *pgwin32_toUTF16(const char *str, int len, int *utf16len);
#endif
#endif /* PG_WCHAR_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment