sigar/bindings/java/src/jni/win32/eventlog.c

353 lines
9.8 KiB
C
Raw Normal View History

2006-07-16 01:46:36 +08:00
/*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of SIGAR.
*
* SIGAR is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program is distributed
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
2004-11-21 05:01:16 +08:00
#ifdef WIN32
#include "javasigar.h"
#include "win32bindings.h"
#define MAX_MSG_LENGTH 8192
2004-11-21 05:01:16 +08:00
#define MAX_ERROR_LENGTH 1024
#define REG_MSGFILE_ROOT "SYSTEM\\CurrentControlSet\\Services\\EventLog\\"
static void win32_set_pointer(JNIEnv *env, jobject obj, const void *ptr)
{
jfieldID pointer_field;
int pointer_int;
jclass cls;
cls = JENV->GetObjectClass(env, obj);
pointer_field = JENV->GetFieldID(env, cls, "eventLogHandle", "I");
pointer_int = (int)ptr;
JENV->SetIntField(env, obj, pointer_field, pointer_int);
}
static HANDLE win32_get_pointer(JNIEnv *env, jobject obj)
{
jfieldID pointer_field;
HANDLE h;
jclass cls;
cls = JENV->GetObjectClass(env, obj);
pointer_field = JENV->GetFieldID(env, cls, "eventLogHandle", "I");
h = (HANDLE)JENV->GetIntField(env, obj, pointer_field);
if (!h) {
win32_throw_exception(env, "Event log not opened");
}
return h;
}
static int get_messagefile_dll(const char *app, char *source, char *dllfile)
2004-11-21 05:01:16 +08:00
{
HKEY hk;
char buf[MAX_MSG_LENGTH];
2005-09-23 10:31:43 +08:00
DWORD type, data = sizeof(buf);
LONG rc;
2004-11-21 05:01:16 +08:00
sprintf(buf, "%s%s\\%s", REG_MSGFILE_ROOT, app, source);
rc = RegOpenKey(HKEY_LOCAL_MACHINE, buf, &hk);
if (rc) {
return rc;
2004-11-21 05:01:16 +08:00
}
rc = RegQueryValueEx(hk, "EventMessageFile", NULL, &type,
(UCHAR *)buf, &data);
if (rc) {
2004-11-21 05:01:16 +08:00
RegCloseKey(hk);
return rc;
2004-11-21 05:01:16 +08:00
}
2005-09-23 10:31:43 +08:00
strncpy(dllfile, buf, MAX_MSG_LENGTH);
2005-09-25 05:16:29 +08:00
dllfile[MAX_MSG_LENGTH-1] = '\0';
2004-11-21 05:01:16 +08:00
RegCloseKey(hk);
return ERROR_SUCCESS;
2004-11-21 05:01:16 +08:00
}
static int get_formatted_message(EVENTLOGRECORD *pevlr, char *dllfile,
char *msg)
{
HINSTANCE hlib;
2005-09-25 05:16:29 +08:00
LPVOID msgbuf;
2004-11-21 05:01:16 +08:00
char msgdll[MAX_MSG_LENGTH];
2005-09-25 05:16:29 +08:00
char *insert_strs[16], *ch;
int i, max = sizeof(insert_strs) / sizeof(char *);
2005-09-24 12:37:55 +08:00
DWORD result;
2004-11-21 05:01:16 +08:00
if (!ExpandEnvironmentStrings(dllfile, msgdll, MAX_PATH))
return GetLastError();
if (!(hlib = LoadLibraryEx(msgdll, NULL,
LOAD_LIBRARY_AS_DATAFILE)))
return GetLastError();
2005-09-25 05:16:29 +08:00
memset(insert_strs, '\0', sizeof(insert_strs));
2004-11-21 05:01:16 +08:00
ch = (char *)((LPBYTE)pevlr + pevlr->StringOffset);
2005-09-25 05:16:29 +08:00
for (i = 0; i < pevlr->NumStrings && i < max; i++) {
2004-11-21 05:01:16 +08:00
insert_strs[i] = ch;
2005-09-25 05:16:29 +08:00
if (ch == NULL) {
break;
}
2004-11-21 05:01:16 +08:00
ch += strlen(ch) + 1;
}
2005-09-24 12:37:55 +08:00
result =
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
2005-09-25 05:16:29 +08:00
FORMAT_MESSAGE_FROM_SYSTEM |
2005-09-24 12:37:55 +08:00
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_ARGUMENT_ARRAY,
hlib,
pevlr->EventID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_ENGLISH_US),
(LPTSTR) &msgbuf,
2005-09-25 05:16:29 +08:00
MAX_MSG_LENGTH,
2005-09-24 12:37:55 +08:00
insert_strs);
if (result) {
strncpy(msg, msgbuf, MAX_MSG_LENGTH);
2005-09-25 05:16:29 +08:00
msg[MAX_MSG_LENGTH-1] = '\0';
result = ERROR_SUCCESS;
LocalFree(msgbuf);
2005-09-24 12:37:55 +08:00
}
else {
result = GetLastError();
}
2004-11-21 05:01:16 +08:00
FreeLibrary(hlib);
2005-09-24 12:37:55 +08:00
return result;
2004-11-21 05:01:16 +08:00
}
JNIEXPORT void SIGAR_JNI(win32_EventLog_openlog)
2004-11-21 05:01:16 +08:00
(JNIEnv *env, jobject obj, jstring lpSourceName)
{
HANDLE h;
const char *name;
name = JENV->GetStringUTFChars(env, lpSourceName, 0);
h = OpenEventLog(NULL, name);
if (h == NULL) {
char buf[MAX_ERROR_LENGTH];
DWORD lastError = GetLastError();
sprintf(buf, "Unable to open event log: %d", lastError);
JENV->ReleaseStringUTFChars(env, lpSourceName, name);
win32_throw_exception(env, buf);
return;
}
JENV->ReleaseStringUTFChars(env, lpSourceName, name);
/* Save the handle for later use */
win32_set_pointer(env, obj, h);
}
JNIEXPORT void SIGAR_JNI(win32_EventLog_close)
(JNIEnv *env, jobject obj)
{
HANDLE h = win32_get_pointer(env, obj);
CloseEventLog(h);
win32_set_pointer(env, obj, NULL);
}
JNIEXPORT jint SIGAR_JNI(win32_EventLog_getNumberOfRecords)
(JNIEnv *env, jobject obj)
{
DWORD records;
HANDLE h = win32_get_pointer(env, obj);
2005-09-25 05:16:29 +08:00
if (!GetNumberOfEventLogRecords(h, &records)) {
win32_throw_last_error(env);
return 0;
}
2004-11-21 05:01:16 +08:00
return records;
}
JNIEXPORT jint SIGAR_JNI(win32_EventLog_getOldestRecord)
(JNIEnv *env, jobject obj)
{
DWORD oldest;
HANDLE h = win32_get_pointer(env, obj);
2005-09-25 05:16:29 +08:00
if (!GetOldestEventLogRecord(h, &oldest)) {
win32_throw_last_error(env);
return 0;
}
2004-11-21 05:01:16 +08:00
return oldest;
}
JNIEXPORT jobject SIGAR_JNI(win32_EventLog_readlog)
(JNIEnv *env, jobject obj, jstring jname, jint recordOffset)
2004-11-21 05:01:16 +08:00
{
EVENTLOGRECORD *pevlr;
BYTE buffer[8192];
2005-09-23 10:31:43 +08:00
char dllfile[MAX_MSG_LENGTH];
char msg[MAX_MSG_LENGTH];
2004-11-21 05:01:16 +08:00
DWORD dwRead, dwNeeded;
LPSTR source, machineName;
HANDLE h;
BOOL rv;
jclass cls = WIN32_FIND_CLASS("EventLogRecord");
jobject eventObj; /* Actual instance of the EventLogRecord */
jfieldID id;
const char *name;
2004-11-21 05:01:16 +08:00
h = win32_get_pointer(env, obj);
pevlr = (EVENTLOGRECORD *)&buffer;
rv = ReadEventLog(h,
EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ,
recordOffset,
pevlr,
sizeof(buffer),
&dwRead,
&dwNeeded);
if (!rv) {
char buf[MAX_ERROR_LENGTH];
DWORD lastError = GetLastError();
if (lastError == ERROR_INSUFFICIENT_BUFFER) {
/* XXX need to handle this */
sprintf(buf, "Buffer size (%d) too small (%d needed)",
sizeof(buffer), dwNeeded);
}
else {
sprintf(buf, "Error reading from the event log: %d", lastError);
}
2004-11-21 05:01:16 +08:00
win32_throw_exception(env, buf);
return NULL;
}
eventObj = JENV->AllocObject(env, cls);
id = JENV->GetFieldID(env, cls, "recordNumber", "J");
JENV->SetLongField(env, eventObj, id, pevlr->RecordNumber);
id = JENV->GetFieldID(env, cls, "timeGenerated", "J");
JENV->SetLongField(env, eventObj, id, pevlr->TimeGenerated);
id = JENV->GetFieldID(env, cls, "timeWritten", "J");
JENV->SetLongField(env, eventObj, id, pevlr->TimeWritten);
id = JENV->GetFieldID(env, cls, "eventId", "J");
JENV->SetLongField(env, eventObj, id, pevlr->EventID);
id = JENV->GetFieldID(env, cls, "eventType", "S");
JENV->SetShortField(env, eventObj, id, pevlr->EventType);
/* Extract string data from the end of the structure. Lame. */
id = JENV->GetFieldID(env, cls, "source", "Ljava/lang/String;");
source = (LPSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD));
SetStringField(env, eventObj, id, source);
name = JENV->GetStringUTFChars(env, jname, 0);
2004-11-21 05:01:16 +08:00
/* Get the formatted message */
2005-09-25 05:16:29 +08:00
if ((pevlr->NumStrings > 0) &&
(get_messagefile_dll(name, source, dllfile) == ERROR_SUCCESS) &&
(get_formatted_message(pevlr, dllfile, msg) == ERROR_SUCCESS))
{
id = JENV->GetFieldID(env, cls, "message",
"Ljava/lang/String;");
SetStringField(env, eventObj, id, msg);
2005-09-25 05:16:29 +08:00
}
else if (pevlr->NumStrings > 0) {
2004-11-21 05:01:16 +08:00
char *tmp = (LPSTR)((LPBYTE)pevlr + pevlr->StringOffset);
id = JENV->GetFieldID(env, cls, "message", "Ljava/lang/String;");
2004-11-21 05:01:16 +08:00
SetStringField(env, eventObj, id, tmp);
}
JENV->ReleaseStringUTFChars(env, jname, name);
2004-11-21 05:01:16 +08:00
/* Increment up to the machine name. */
id = JENV->GetFieldID(env, cls, "computerName", "Ljava/lang/String;");
machineName = (LPSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD) +
strlen(source) + 1);
SetStringField(env, eventObj, id, machineName);
/* Get user id info */
if (pevlr->UserSidLength > 0) {
char name[256];
char domain[256];
DWORD namelen = sizeof(name);
DWORD domainlen = sizeof(domain);
DWORD len;
SID_NAME_USE snu;
PSID sid;
sid = (PSID)((LPBYTE)pevlr + pevlr->UserSidOffset);
if (LookupAccountSid(NULL, sid, name, &namelen, domain,
&domainlen, &snu)) {
id = JENV->GetFieldID(env, cls, "user", "Ljava/lang/String;");
SetStringField(env, eventObj, id, name);
}
}
return eventObj;
}
JNIEXPORT void SIGAR_JNI(win32_EventLog_waitForChange)
(JNIEnv *env, jobject obj, jint timeout)
{
HANDLE h, hEvent;
DWORD millis;
h = win32_get_pointer(env, obj);
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hEvent == NULL) {
win32_throw_exception(env, "Unable to create event");
return;
}
if (timeout == -1)
millis = INFINITE;
else
millis = timeout;
if(!(NotifyChangeEventLog(h, hEvent))) {
char buf[MAX_ERROR_LENGTH];
sprintf(buf, "Error registering for event log to change: %d",
GetLastError());
win32_throw_exception(env, buf);
return;
}
if (WaitForSingleObject(hEvent, millis) == WAIT_FAILED)
{
char buf[MAX_ERROR_LENGTH];
sprintf(buf, "Error waiting for event log change: %d",
GetLastError());
win32_throw_exception(env, buf);
}
return;
}
#endif /* WIN32 */