Write to the Windows eventlog in UTF16, converting the message encoding
as necessary. Itagaki Takahiro with some changes from me
This commit is contained in:
parent
76c09dbe8d
commit
748771379b
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
ReportEvent(evtHandle,
|
||||
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 */
|
||||
|
|
Loading…
Reference in New Issue