(SIGAR-134) use UNICODE in EventLog wrapper

This commit is contained in:
Doug MacEachern 2009-02-12 16:32:36 -08:00
parent 168c14e0ff
commit 39af88f8c5
1 changed files with 70 additions and 64 deletions

View File

@ -17,13 +17,25 @@
*/ */
#ifdef WIN32 #ifdef WIN32
#define UNICODE
#define _UNICODE
#include "javasigar.h" #include "javasigar.h"
#include "win32bindings.h" #include "win32bindings.h"
#define MAX_MSG_LENGTH 8192 #define MAX_MSG_LENGTH 8192
#define MAX_ERROR_LENGTH 1024 #define MAX_ERROR_LENGTH 1024
#define REG_MSGFILE_ROOT "SYSTEM\\CurrentControlSet\\Services\\EventLog\\" #define REG_MSGFILE_ROOT L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\"
#define FILESEP L";"
#define STRING_SIG "Ljava/lang/String;"
#define UNICODE_SetStringField(field, str) \
id = JENV->GetFieldID(env, cls, field, STRING_SIG); \
value = JENV->NewString(env, (const jchar *)str, wcslen(str)); \
JENV->SetObjectField(env, obj, id, value)
#define ARRLEN(arr) (sizeof(arr) / sizeof(arr[0]))
static void win32_set_pointer(JNIEnv *env, jobject obj, const void *ptr) static void win32_set_pointer(JNIEnv *env, jobject obj, const void *ptr)
{ {
@ -57,27 +69,32 @@ static HANDLE win32_get_pointer(JNIEnv *env, jobject obj)
return h; return h;
} }
static int get_messagefile_dll(const char *app, char *source, char *dllfile) static int get_messagefile_dll(LPWSTR app, LPWSTR source, LPWSTR dllfile)
{ {
HKEY hk; HKEY hk;
char buf[MAX_MSG_LENGTH]; WCHAR buf[MAX_MSG_LENGTH];
DWORD type, data = sizeof(buf); DWORD type, data = sizeof(buf);
LONG rc; LONG rc;
sprintf(buf, "%s%s\\%s", REG_MSGFILE_ROOT, app, source); wcscpy(buf, REG_MSGFILE_ROOT);
rc = RegOpenKey(HKEY_LOCAL_MACHINE, buf, &hk); wcscat(buf, app);
wcscat(buf, L"\\");
wcscat(buf, source);
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf,
0, KEY_READ, &hk);
if (rc) { if (rc) {
return rc; return rc;
} }
rc = RegQueryValueEx(hk, "EventMessageFile", NULL, &type, rc = RegQueryValueEx(hk, L"EventMessageFile", NULL, &type,
(UCHAR *)buf, &data); (LPBYTE)buf, &data);
if (rc) { if (rc) {
RegCloseKey(hk); RegCloseKey(hk);
return rc; return rc;
} }
strncpy(dllfile, buf, MAX_MSG_LENGTH); wcsncpy(dllfile, buf, MAX_MSG_LENGTH);
dllfile[MAX_MSG_LENGTH-1] = '\0'; dllfile[MAX_MSG_LENGTH-1] = '\0';
RegCloseKey(hk); RegCloseKey(hk);
@ -85,13 +102,13 @@ static int get_messagefile_dll(const char *app, char *source, char *dllfile)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static int get_formatted_message(EVENTLOGRECORD *pevlr, char *dllfile, static int get_formatted_message(EVENTLOGRECORD *pevlr, LPWSTR dllfile,
char *msg) LPWSTR msg)
{ {
LPVOID msgbuf = NULL; LPVOID msgbuf = NULL;
char msgdll[MAX_MSG_LENGTH]; WCHAR msgdll[MAX_MSG_LENGTH];
char *insert_strs[56], *ptr; LPWSTR insert_strs[56], ptr;
int i, max = sizeof(insert_strs) / sizeof(char *); int i, max = ARRLEN(insert_strs);
const DWORD flags = const DWORD flags =
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_HMODULE |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_SYSTEM |
@ -99,25 +116,20 @@ static int get_formatted_message(EVENTLOGRECORD *pevlr, char *dllfile,
FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_ARGUMENT_ARRAY |
FORMAT_MESSAGE_MAX_WIDTH_MASK; FORMAT_MESSAGE_MAX_WIDTH_MASK;
if (!ExpandEnvironmentStrings(dllfile, msgdll, sizeof(msgdll))) { if (!ExpandEnvironmentStrings(dllfile, msgdll, ARRLEN(msgdll))) {
return GetLastError(); return GetLastError();
} }
memset(insert_strs, '\0', sizeof(insert_strs)); memset(insert_strs, '\0', sizeof(insert_strs));
ptr = (char *)((LPBYTE)pevlr + pevlr->StringOffset); ptr = (LPWSTR)((LPBYTE)pevlr + pevlr->StringOffset);
for (i = 0; i < pevlr->NumStrings && i < max; i++) { for (i = 0; i < pevlr->NumStrings && i < max; i++) {
insert_strs[i] = ptr; insert_strs[i] = ptr;
ptr += strlen(ptr) + 1; ptr += wcslen(ptr) + 1;
} }
ptr = msgdll; ptr = wcstok(msgdll, FILESEP);
while (ptr) { while (ptr) {
HINSTANCE hlib; HINSTANCE hlib;
char *delim = strchr(ptr, ';');
if (delim) {
*delim++ = '\0';
}
hlib = LoadLibraryEx(ptr, NULL, hlib = LoadLibraryEx(ptr, NULL,
LOAD_LIBRARY_AS_DATAFILE); LOAD_LIBRARY_AS_DATAFILE);
@ -126,20 +138,20 @@ static int get_formatted_message(EVENTLOGRECORD *pevlr, char *dllfile,
hlib, hlib,
pevlr->EventID, pevlr->EventID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_ENGLISH_US), MAKELANGID(LANG_NEUTRAL, SUBLANG_ENGLISH_US),
(LPTSTR) &msgbuf, (LPWSTR) &msgbuf,
sizeof(msgbuf), sizeof(msgbuf), //min bytes w/ FORMAT_MESSAGE_ALLOCATE_BUFFER
insert_strs); (va_list *)insert_strs);
FreeLibrary(hlib); FreeLibrary(hlib);
if (msgbuf) { if (msgbuf) {
break; break;
} }
} }
ptr = delim; ptr = wcstok(NULL, FILESEP);
} }
if (msgbuf) { if (msgbuf) {
strncpy(msg, msgbuf, MAX_MSG_LENGTH); wcsncpy(msg, msgbuf, MAX_MSG_LENGTH);
msg[MAX_MSG_LENGTH-1] = '\0'; msg[MAX_MSG_LENGTH-1] = '\0';
LocalFree(msgbuf); LocalFree(msgbuf);
return ERROR_SUCCESS; return ERROR_SUCCESS;
@ -153,9 +165,9 @@ JNIEXPORT void SIGAR_JNI(win32_EventLog_openlog)
(JNIEnv *env, jobject obj, jstring lpSourceName) (JNIEnv *env, jobject obj, jstring lpSourceName)
{ {
HANDLE h; HANDLE h;
const char *name; LPWSTR name;
name = JENV->GetStringUTFChars(env, lpSourceName, 0); name = (LPWSTR)JENV->GetStringChars(env, lpSourceName, NULL);
h = OpenEventLog(NULL, name); h = OpenEventLog(NULL, name);
if (h == NULL) { if (h == NULL) {
@ -163,12 +175,12 @@ JNIEXPORT void SIGAR_JNI(win32_EventLog_openlog)
DWORD lastError = GetLastError(); DWORD lastError = GetLastError();
sprintf(buf, "Unable to open event log: %d", lastError); sprintf(buf, "Unable to open event log: %d", lastError);
JENV->ReleaseStringUTFChars(env, lpSourceName, name); JENV->ReleaseStringChars(env, lpSourceName, name);
win32_throw_exception(env, buf); win32_throw_exception(env, buf);
return; return;
} }
JENV->ReleaseStringUTFChars(env, lpSourceName, name); JENV->ReleaseStringChars(env, lpSourceName, name);
/* Save the handle for later use */ /* Save the handle for later use */
win32_set_pointer(env, obj, h); win32_set_pointer(env, obj, h);
@ -217,16 +229,16 @@ JNIEXPORT jobject SIGAR_JNI(win32_EventLog_readlog)
{ {
EVENTLOGRECORD *pevlr; EVENTLOGRECORD *pevlr;
BYTE buffer[8192]; BYTE buffer[8192];
char dllfile[MAX_MSG_LENGTH]; WCHAR dllfile[MAX_MSG_LENGTH];
char msg[MAX_MSG_LENGTH]; WCHAR msg[MAX_MSG_LENGTH];
DWORD dwRead, dwNeeded; DWORD dwRead, dwNeeded;
LPSTR source, machineName; LPWSTR source, machineName;
HANDLE h; HANDLE h;
BOOL rv; BOOL rv;
jclass cls = WIN32_FIND_CLASS("EventLogRecord"); jclass cls = WIN32_FIND_CLASS("EventLogRecord");
jobject eventObj; /* Actual instance of the EventLogRecord */
jfieldID id; jfieldID id;
const char *name; jstring value;
LPWSTR name;
h = win32_get_pointer(env, obj); h = win32_get_pointer(env, obj);
@ -254,59 +266,54 @@ JNIEXPORT jobject SIGAR_JNI(win32_EventLog_readlog)
return NULL; return NULL;
} }
eventObj = JENV->AllocObject(env, cls); obj = JENV->AllocObject(env, cls);
id = JENV->GetFieldID(env, cls, "recordNumber", "J"); id = JENV->GetFieldID(env, cls, "recordNumber", "J");
JENV->SetLongField(env, eventObj, id, pevlr->RecordNumber); JENV->SetLongField(env, obj, id, pevlr->RecordNumber);
id = JENV->GetFieldID(env, cls, "timeGenerated", "J"); id = JENV->GetFieldID(env, cls, "timeGenerated", "J");
JENV->SetLongField(env, eventObj, id, pevlr->TimeGenerated); JENV->SetLongField(env, obj, id, pevlr->TimeGenerated);
id = JENV->GetFieldID(env, cls, "timeWritten", "J"); id = JENV->GetFieldID(env, cls, "timeWritten", "J");
JENV->SetLongField(env, eventObj, id, pevlr->TimeWritten); JENV->SetLongField(env, obj, id, pevlr->TimeWritten);
id = JENV->GetFieldID(env, cls, "eventId", "J"); id = JENV->GetFieldID(env, cls, "eventId", "J");
JENV->SetLongField(env, eventObj, id, pevlr->EventID); JENV->SetLongField(env, obj, id, pevlr->EventID);
id = JENV->GetFieldID(env, cls, "eventType", "S"); id = JENV->GetFieldID(env, cls, "eventType", "S");
JENV->SetShortField(env, eventObj, id, pevlr->EventType); JENV->SetShortField(env, obj, id, pevlr->EventType);
/* Extract string data from the end of the structure. Lame. */ /* Extract string data from the end of the structure. Lame. */
id = JENV->GetFieldID(env, cls, "source", "Ljava/lang/String;"); source = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD));
source = (LPSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD)); UNICODE_SetStringField("source", source);
SetStringField(env, eventObj, id, source);
name = JENV->GetStringUTFChars(env, jname, 0); name = (LPWSTR)JENV->GetStringChars(env, jname, NULL);
/* Get the formatted message */ /* Get the formatted message */
if ((pevlr->NumStrings > 0) && if ((pevlr->NumStrings > 0) &&
(get_messagefile_dll(name, source, dllfile) == ERROR_SUCCESS) && (get_messagefile_dll(name, source, dllfile) == ERROR_SUCCESS) &&
(get_formatted_message(pevlr, dllfile, msg) == ERROR_SUCCESS)) (get_formatted_message(pevlr, dllfile, msg) == ERROR_SUCCESS))
{ {
id = JENV->GetFieldID(env, cls, "message", UNICODE_SetStringField("message", msg);
"Ljava/lang/String;");
SetStringField(env, eventObj, id, msg);
} }
else if (pevlr->NumStrings > 0) { else if (pevlr->NumStrings > 0) {
char *tmp = (LPSTR)((LPBYTE)pevlr + pevlr->StringOffset); LPWSTR tmp = (LPWSTR)((LPBYTE)pevlr + pevlr->StringOffset);
id = JENV->GetFieldID(env, cls, "message", "Ljava/lang/String;"); UNICODE_SetStringField("message", tmp);
SetStringField(env, eventObj, id, tmp);
} }
JENV->ReleaseStringUTFChars(env, jname, name); JENV->ReleaseStringChars(env, jname, name);
/* Increment up to the machine name. */ /* Increment up to the machine name. */
id = JENV->GetFieldID(env, cls, "computerName", "Ljava/lang/String;"); machineName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD) +
machineName = (LPSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD) + wcslen(source) + 1);
strlen(source) + 1); UNICODE_SetStringField("computerName", machineName);
SetStringField(env, eventObj, id, machineName);
/* Get user id info */ /* Get user id info */
if (pevlr->UserSidLength > 0) { if (pevlr->UserSidLength > 0) {
char name[256]; WCHAR name[256];
char domain[256]; WCHAR domain[256];
DWORD namelen = sizeof(name); DWORD namelen = ARRLEN(name);
DWORD domainlen = sizeof(domain); DWORD domainlen = ARRLEN(domain);
DWORD len; DWORD len;
SID_NAME_USE snu; SID_NAME_USE snu;
PSID sid; PSID sid;
@ -314,12 +321,11 @@ JNIEXPORT jobject SIGAR_JNI(win32_EventLog_readlog)
sid = (PSID)((LPBYTE)pevlr + pevlr->UserSidOffset); sid = (PSID)((LPBYTE)pevlr + pevlr->UserSidOffset);
if (LookupAccountSid(NULL, sid, name, &namelen, domain, if (LookupAccountSid(NULL, sid, name, &namelen, domain,
&domainlen, &snu)) { &domainlen, &snu)) {
id = JENV->GetFieldID(env, cls, "user", "Ljava/lang/String;"); UNICODE_SetStringField("user", name);
SetStringField(env, eventObj, id, name);
} }
} }
return eventObj; return obj;
} }
JNIEXPORT void SIGAR_JNI(win32_EventLog_waitForChange) JNIEXPORT void SIGAR_JNI(win32_EventLog_waitForChange)