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

314 lines
8.6 KiB
C
Raw Normal View History

2004-11-21 05:01:16 +08:00
#ifdef WIN32
#include "javasigar.h"
#include "win32bindings.h"
#define MAX_INSERT_STRS 8
#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;
DWORD type, data;
char buf[MAX_MSG_LENGTH];
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
}
strncpy(dllfile, buf, sizeof(dllfile));
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;
LPTSTR msgbuf;
char msgdll[MAX_MSG_LENGTH];
char *insert_strs[MAX_INSERT_STRS], *ch;
int i;
if (!ExpandEnvironmentStrings(dllfile, msgdll, MAX_PATH))
return GetLastError();
if (!(hlib = LoadLibraryEx(msgdll, NULL,
LOAD_LIBRARY_AS_DATAFILE)))
return GetLastError();
ch = (char *)((LPBYTE)pevlr + pevlr->StringOffset);
for (i = 0; i < pevlr->NumStrings && i < MAX_INSERT_STRS; i++) {
insert_strs[i] = ch;
ch += strlen(ch) + 1;
}
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_ARGUMENT_ARRAY,
hlib,
pevlr->EventID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_ENGLISH_US),
(LPTSTR) &msgbuf,
MAX_MSG_LENGTH,
insert_strs);
strncpy(msg, msgbuf, sizeof(msg));
FreeLibrary(hlib);
LocalFree((HLOCAL)msgbuf);
return 0;
}
JNIEXPORT void SIGAR_JNI(win32_EventLog_open)
(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);
GetNumberOfEventLogRecords(h, &records);
return records;
}
JNIEXPORT jint SIGAR_JNI(win32_EventLog_getOldestRecord)
(JNIEnv *env, jobject obj)
{
DWORD oldest;
HANDLE h = win32_get_pointer(env, obj);
GetOldestEventLogRecord(h, &oldest);
return oldest;
}
JNIEXPORT jobject SIGAR_JNI(win32_EventLog_read)
(JNIEnv *env, jobject obj, jstring jname, jint recordOffset)
2004-11-21 05:01:16 +08:00
{
EVENTLOGRECORD *pevlr;
BYTE buffer[8192];
char dllfile[1024];
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 */
if ((get_messagefile_dll(name, source, dllfile) == ERROR_SUCCESS) &&
(get_formatted_message(pevlr, dllfile, msg) == ERROR_SUCCESS))
{
id = JENV->GetFieldID(env, cls, "stringData",
"Ljava/lang/String;");
SetStringField(env, eventObj, id, msg);
2004-11-21 05:01:16 +08:00
} else if (pevlr->StringOffset > 0) {
/* Work around some applications not using a message file */
char *tmp = (LPSTR)((LPBYTE)pevlr + pevlr->StringOffset);
id = JENV->GetFieldID(env, cls, "stringData", "Ljava/lang/String;");
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 */